3

I have a Spring (Boot) application on which I'm trying to use Hibernate Envers.

The following bar function throws an IllegalStateException: EntityManager is closed, while the foo function works flawlessly:

@Service
public class FoobarService {

    private final EntityManager entityManager;

    @Autowired
    public FoobarService(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public Iterable<Foobar> foo() {
        return entityManager.createQuery("select f from Foobar f", Foobar.class).getResultList();
    }

    public Iterable<Foobar> bar() {
        System.out.println(entityManager.isOpen()); // <--- Returns true!

        AuditReader auditReader = AuditReaderFactory.get(entityManager);
        AuditQueryCreator queryCreator = auditReader.createQuery();
        AuditQuery query = queryCreator.forRevisionsOfEntity(Foobar.class, true);

        return query.getResultList();
    }

}

Does anybody know why it claims it's closed when the foo function clearly works (as stated above)?

PS: I've omitted the maven dependencies and entity mapping for brevity, as they're all working.

EDIT:

There's something really weird I can't figure out. Within the bar function, we can see that:

  1. entityManager.isOpen() returns true
  2. ((Session) entityManager.getDelegate()).isOpen() returns false

The AuditReaderFactory.get(EntityManager entityManager) function uses the second, this is why it complains the session is closed when it's not. I don't quite get why the delegate is closed, so:

  1. Why does the the factory uses the entityManager's delegate instead?
  2. Why the delegate is even closed?
Yves Calaci
  • 1,019
  • 1
  • 11
  • 37
  • 1
    Check this out https://stackoverflow.com/a/51858463/3881354 – Elyas Hadizadeh Nov 25 '20 at 04:46
  • 1
    I was thinking of creating a Configuration for Hibernate Envers indeed, however this approach is the same as injecting an `PersistenceContext` (EntityManager) of type `PersistenceContextType.EXTENDED`. In other words, both approaches return an application-managed `EntityManager`, on which should be avoided, am I right? – Yves Calaci Nov 25 '20 at 04:56
  • @ElyasHadizadeh the answer you linked is wrong. Mine is correct: https://stackoverflow.com/a/70177753/554117 – Giulio Pulina May 06 '23 at 09:39

1 Answers1

0

I think I had the same issue, when running a @SpringBootTest I needed to get a hold of EntityManager like they showed in the Envers user-guide.

If you go to Hibernate Envers github-project tests, you can see that they use the factory to get the EntityManager.

I tried to annotate my EntityManager in the test with either @Autowire or @PersistenceContext, in both cases EntityManager object was opened but the delegate was closed like in your case. It only worked when I autowired the factory:

@Autowired
private EntityManagerFactory entityManagerFactory;

And then created an entityManager for my test like this:

var entityManager = entityManagerFactory.createEntityManager();
Mihai
  • 1
  • 1