Jersey, Guice and Hibernate - EntityManager thread safety

后端 未结 3 647
轮回少年
轮回少年 2021-01-17 05:40

I have used this tutorial them same way in my application: http://www.benmccann.com/hibernate-with-jpa-annotations-and-guice/

My app is JAX-RS web service which will

相关标签:
3条回答
  • 2021-01-17 05:50

    The problem was that my endpoint was annotated with @Singleton so it reused the same EntityManager during concurrent calls. After removing @Singleton, during concurrent calls, different EntityManager objects are used. If endpoint calls are subsequent, it may be that previous/old EntityManager will be used.

    Highly simplified example:

    @Path("/v1/items")
    public class ItemsService {
    
        @Inject
        private EntityManager entityManager;
    
        @POST
        @Path("/{id}")
        @Consumes(MediaType.APPLICATION_JSON)
        @Produces(MediaType.APPLICATION_JSON)
        public void saveItem(){
             entityManager.getTransaction().begin();
             entityManager.persist(new Item());
             entityManager.getTransaction().commit();
        }
    }
    
    0 讨论(0)
  • 2021-01-17 06:05

    First of all, what kind of EntityManager are you using? Looking at your code I suposse this kind is Application-Managed EntityManager. It would be important for you to understand the different types of EntityManager.

    Please see: http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html

    Basing on this, you need to create an EntityManagerFactory object and then create an EntityManager object.

    Basic Example:

    private static EntityManagerFactory emf; 
    EntityManager em = null;
    
    public static EntityManagerFactory getEmf(){
        if(emf == null){
            emf = Persistence.createEntityManagerFactory("nameOfYourPersistenceUnit");
        }
        return emf;
    }
    
    
    em = getEmf().createEntityManager();
    em.getTransaction().begin();
    em.persist(entity);
    em.getTransaction().commit();
    em.close();
    
    0 讨论(0)
  • 2021-01-17 06:16

    If it says that the transaction is already open, that means that it was open by another process and not closed ...

    I suggest to use @Transactionl instead of Writing :

    em.getTransaction().begin();
    

    and

    em.getTransaction().commit();
    em.close();
    

    That will manage the things for you ...

    so for you it will be this way :

    @Transactionl
    @POST
    @Path("/{id}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public void saveItem(){
         entityManager.persist(new Item());
    }
    

    Hope that's help

    0 讨论(0)
提交回复
热议问题