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

使用时guice-persistEntityManager是事务范围的。如果我理解正确的话,这意味着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();

      }



蝴蝶不菲
浏览 112回答 1
1回答

江户川乱折腾

上面的代码有两个问题:1)下面一行System.out.println("TEST:&nbsp;"&nbsp;+"EntityManager:&nbsp;"&nbsp;+&nbsp;projectService.getEntityManager().hashCode());被添加用于调试目的。ProjectService.getEntityManager()但是,调用 的方法ProjectDAO.getEntityManager()又调用entityManagerProvider.get(),没有用 注释@Transactional。这会导致EntityManager每个线程设置一次并且永远不会取消设置,即使@Transactional稍后调用 ProjectService 中具有注释的其他方法也是如此。只需添加此注释即可解决问题。2)在一个线程中,名称为“project1”的实体被删除&nbsp;&nbsp;&nbsp;//---- &nbsp;&nbsp;&nbsp;projectService.delete("project1"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//----然而,在另一个线程中,验证了另一个实体的存在&nbsp;&nbsp;&nbsp;//&nbsp;project3,&nbsp;which&nbsp;was&nbsp;deleted&nbsp;in&nbsp;Thread&nbsp;2&nbsp;is&nbsp;still&nbsp;visible&nbsp;in&nbsp;this&nbsp;EntityManager &nbsp;&nbsp;&nbsp;Project&nbsp;project&nbsp;=&nbsp;projectService.findById(3L); &nbsp;&nbsp;&nbsp;System.out.println("Project&nbsp;still&nbsp;exists&nbsp;"&nbsp;+&nbsp;project);一开始就没有删除。实体被一个接一个地添加 - project1、project2、project3... 并分别为它们分配 ID 1、2、3...。所以代码应该是&nbsp;&nbsp;&nbsp;//&nbsp;project1,&nbsp;which&nbsp;was&nbsp;deleted&nbsp;in&nbsp;Thread&nbsp;2&nbsp;is&nbsp;still&nbsp;visible&nbsp;in&nbsp;this&nbsp;EntityManager &nbsp;&nbsp;&nbsp;Project&nbsp;project&nbsp;=&nbsp;projectService.findById(1L); &nbsp;&nbsp;&nbsp;System.out.println("Project&nbsp;still&nbsp;exists&nbsp;"&nbsp;+&nbsp;project);
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java