亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何防止使用 guice-persist 和 @Transactional 重用

如何防止使用 guice-persist 和 @Transactional 重用

蝴蝶不菲 2023-06-14 16:20:22
使用時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);


查看完整回答
反對 回復 2023-06-14
  • 1 回答
  • 0 關注
  • 143 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號