使用時guice-persist,EntityManager是事務范圍的。如果我理解正確的話,這意味著EntityManager將為每筆交易創建一個新的。使用時guice-persist,建議使用JpaPersistModule,它提供了所有的綁定,并簡單地注入Provider<EntityManager>到某個類中,就像這樣:public class ProjectDAO {? private final Provider<EntityManager> entityManagerProvider;? @Inject? public ProjectDAO(Provider<EntityManager> entityManagerProvider) {? ? this.entityManagerProvider = entityManagerProvider;? }}?現在,我試過了,每個線程都有自己的EntityManager.?然而,它似乎并沒有被移除并重新設置,而是被重新用于后續事務,即Hibernate的一級緩存沒有被清除。這是一個完整的示例,它從兩個不同的線程(順序地,而不是并行地)插入和刪除一些實體,這會導致一個線程具有陳舊的信息:項目(一個簡單的實體)? ?@NamedQueries({? ? ? ? @NamedQuery(name = "project.findAll", query = "from project"),? ? ? ? @NamedQuery(name = "project.deleteByProjectName", query = "delete from project p where p.name = :project_name")? ? }? ? )? ? @Entity(name = "project")? ? public class Project {? ? ? ? @Id? ? ? ? @GeneratedValue? ? ? ? private Long id;? ? ? ? @Column(name="name")? ? ? ? private String name;? ? ? ? // ... getters/setters? ? }項目DAO? ? public class ProjectDAO {? ? ? private final Provider<EntityManager> entityManagerProvider;? ? ? @Inject? ? ? public ProjectDAO(Provider<EntityManager> entityManagerProvider) {? ? ? ? this.entityManagerProvider = entityManagerProvider;? ? ? }? ? ? public void insert(Project project) {? ? ? ? entityManagerProvider.get().persist(project);? ? ? }? ? ? public List<Project> findAll() {? ? ? ? return entityManagerProvider.get()? ? ? ? ? ? .createNamedQuery("project.findAll", Project.class)? ? ? ? ? ? .getResultList();? ? ? }
1 回答

江戶川亂折騰
TA貢獻1851條經驗 獲得超5個贊
上面的代碼有兩個問題:
1)下面一行
System.out.println("TEST: " +"EntityManager: " + projectService.getEntityManager().hashCode());
被添加用于調試目的。ProjectService.getEntityManager()
但是,調用 的方法ProjectDAO.getEntityManager()
又調用entityManagerProvider.get()
,沒有用 注釋@Transactional
。這會導致EntityManager
每個線程設置一次并且永遠不會取消設置,即使@Transactional
稍后調用 ProjectService 中具有注釋的其他方法也是如此。只需添加此注釋即可解決問題。
2)在一個線程中,名稱為“project1”的實體被刪除
//---- projectService.delete("project1"); //----
然而,在另一個線程中,驗證了另一個實體的存在
// project3, which was deleted in Thread 2 is still visible in this EntityManager Project project = projectService.findById(3L); System.out.println("Project still exists " + project);
一開始就沒有刪除。實體被一個接一個地添加 - project1、project2、project3... 并分別為它們分配 ID 1、2、3...。所以代碼應該是
// project1, which was deleted in Thread 2 is still visible in this EntityManager Project project = projectService.findById(1L); System.out.println("Project still exists " + project);
添加回答
舉報
0/150
提交
取消