2

I am using EntityManagerFactory(injected) to create entityManager each time I need to access the db. I have the following code which throws,

org.springframework.dao.InvalidDataAccessApiUsageException: EntityManager is closed

entityManager = entityManagerFactory.createEntityManager();

List<Object> list = entityManager.createQuery("FROM Class").getResultList();

entityManager.close();

return list.toArray(new Object[list.size()]);

I am creating an EntityManager, querying db for some results, closing EntityManager and returning result to someone who wants those results. I think I can figure out what's wrong. The getResultList() returning objects which are managed. So, trying to access them after closing the EntityManager causing the error(Well, I think...). I tried entityManager.clear() before closing it. I got the same error. I tried detaching each object from the list(entityManager.detach(obj)), before closing it. Still, I got the same error. I tried annotating with @Transactional(readOnly=true) on the method. No use.

I am not going to modify the objects. I just need them to display on the UI. Can you give me a solution for that? I am using Spring boot + hibernate JPA + AngularJS + Postgresql.

(PS: I can't left the entityManager open. Left it open, I got connection limit exceeded error. It is not a best way either)

Igoranze
  • 1,506
  • 13
  • 35
RaR
  • 3,075
  • 3
  • 23
  • 48
  • Could you please share your ApplicationContext.xml file? – Sanjeev Saha Jun 17 '16 at 07:23
  • what type of List is "list" ? a JPA provider one? in which case try copying the elements into your own ArrayList. All objects should become detached at em.close so if getting an exception post the exact exception with its stack trace; some Spring exception is not the real exception ... its nested – Neil Stockton Jun 17 '16 at 07:25
  • @SanjeevSaha I don't have one. I have only `application.properities` file – RaR Jun 17 '16 at 07:37
  • @NeilStockton It's `java.util.list`. I tried what you said. The stack trace is so large to paste here – RaR Jun 17 '16 at 07:38
  • Have you tried simply returning the list of objects from inside the Transactional boundary and then using them in calling method? I would also recommend to check this link to see if you really need to close the entityManager http://stackoverflow.com/questions/10762974/should-jpa-entity-manager-be-closed – Rohit Bansal Jun 17 '16 at 07:39
  • In that case, could you post spring java configuration class and application.properities file? – Sanjeev Saha Jun 17 '16 at 07:40
  • No .... it is an IMPLEMENTATION of a List .... What implementation? list.getClass() – Neil Stockton Jun 17 '16 at 07:43
  • Thank you everyone, for giving your time on this. I solved the problem using the answer below. Anyway, I can't find what's the problem with the older one. Thank you all :) – RaR Jun 17 '16 at 08:04

2 Answers2

7

Why don't you inject the entity manager instead of the factory? This way you can delegate creation and disposal to the framework, gettind also rid of the connection limit error (since the framework will handle all of that for you).

You should be able to inject it this way :

@PersistenceContext
private EntityManager em;

Then you can just use it.

francesco foresti
  • 2,004
  • 20
  • 24
  • 1
    Earlier I tried `@Autowired` on EntityManager. It didn't work. So that I used `EntityManagerFactory`. Thank you for the answer :) – RaR Jun 17 '16 at 08:00
3

I also faced similar issue but it didn't work by just using @PersistenceContext, we need to set PersistenceContextType also which is by default TRANSACTION, but in this case when multiple threads try to use same singleton instance of EntityManager, we need to set it to EXTENDED like this -

@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;

and it worked. I got this issue when i was trying to execute a db query in one of my schedulars.

Reference - https://www.baeldung.com/jpa-hibernate-persistence-context

Anita
  • 93
  • 8
  • 1
    I faced the same problem. I'm using a scheduler to do some work from time to time, and now it is working. You saved my life. – Guilherme Mar 12 '21 at 16:50