3

Runnable で新しいスレッドを作成する Bean があります。

@Component
public class MyBean {

    private final Task task = new Task();

    @PersistenceContext
    EntityManager em;

    @PostConstruct
    public void init() {
        task.setEntityManager(em);
        new Thread(task).start();
    }

    public static class Task implements Runnable {

        @Setter
        private EntityManager em;

        @Override
        public void run() {
            while (true) {
                // working with EntityManager
                Thing t = em.findById(...); // Fetching a Thing from repo
                t.getSomethingList(); // LazyInit exception
                wait();
            }
        }
    }
}

init メソッドで、EntityManager のインスタンスで新しい Thread を作成します。リポジトリから何かをロードしようとすると、セッションが即座に閉じられ、遅延フィールドを取得するとfailed to lazily initialize a collection of role: Something, no session or session was closed、Hibernate から例外が発生します。

@Transactional アノテーションをすべて試しましたが、効果はありませんでした。OpenEntityManagerInView のようなものを達成する必要がありますが、これはビュー内にないという違いがあります。

ありがとう

EDIT1:

  1. コメントによると - 私は使用してみem.getTransaction().begin();ましたが、これは私を取得していますNot allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT

  2. スキルシュは、他の Bean で Transactional メソッドを呼び出すべきだと提案しました。それが私が実際に行っていることです-まさにあなたが提案したとおりです。もっと簡単にしたかったのですが、違いがわからなかったので、クラスで直接問題をデモしましたTask。要約すると、スカーシュが示唆したのとまったく同じですが、問題は解決しません。

4

1 に答える 1

1

Spring は を管理していRunnableないため、注釈を付けても目的の効果は得られません。したがって、注釈付きの (および Spring 管理の) Bean を内部から使用するかRunnable、txn 管理を手動で処理する必要があります。

Spring トランザクション管理を使用する

ある種のサービスを定義します

@Service
public class MyService {
    @PersistenceContext
    EntityManager em;

    @Transactional
    public void doSomething() {
        Thing t = em.findById(...);
        t.getSomethingList();
    }
}

そして、Bean は次のようになります。

@Component
public class MyBean {

    private final Task task = new Task();

    @Autowired
    MyService service;

    @PostConstruct
    public void init() {
        task.setService(service);
        new Thread(task).start();
    }

    public static class Task implements Runnable {

        @Setter
        private MyService service;

        @Override
        public void run() {
            while (true) {
                service.doSomething();
                wait();
            }
        }
    }
}

手動トランザクション管理

JPA リソース ローカル トランザクションを設定する場合は、次のようになります。

// working with EntityManager
em.getTransaction().begin()
try {
    Thing t = em.findById(...);
    t.getSomethingList();
} finally {
    em.getTransaction().rollback()
}
wait();
于 2013-04-20T11:50:03.597 に答える