使用时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
提交
取消