簡體   English   中英

使Hibernate EntityManager處於可運行狀態

[英]Keeping Hibernate EntityManager within a Runnable

我有一個我在其中使用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的實例創建新的線程。 當我嘗試從存儲庫中加載某些內容時,該會話會立即關閉,並且獲取任何惰性字段都會導致failed to lazily initialize a collection of role: Something, no session or session was closed懶惰failed to lazily initialize a collection of role: Something, no session or session was closed Hibernate failed to lazily initialize a collection of role: Something, no session or session was closed

我嘗試了所有@Transactional批注,但沒有任何效果。 我需要實現類似OpenEntityManagerInView的功能,但是區別在於它不在視圖之內。

謝謝

EDIT1:

  1. 根據評論-我嘗試使用em.getTransaction().begin(); 但這讓我Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT

  2. skirsch建議我應該在其他bean上調用Transactional方法。 那就是我實際上所做的-完全按照您的建議。 我想簡化事情,沒有意識到區別,所以我直接在Task類中演示了該問題。 因此,總而言之,我完全按照skirsch的建議進行操作,但是問題仍然存在。

由於Spring不管理您的Runnable ,因此對其進行注釋將不會達到預期的效果。 因此,您需要在Runnable使用帶注釋(且受Spring管理)的Bean,或者需要手動進行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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM