Affects: Spring Framework 5.3.21

A bean method shown below throws exception at the marked line:

    public void doTest() {
        Query q = em.createNativeQuery("select :n");
        q.setParameter("n", 1);
        log.info("result: {}", q.getSingleResult());
        q.setParameter("n", 2);     // <- exception
        log.info("result: {}", q.getSingleResult());
    }

Exception stack:

Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65)
Caused by: java.lang.IllegalStateException: Session/EntityManager is closed
        at org.hibernate.internal.AbstractSharedSessionContract.checkOpen(AbstractSharedSessionContract.java:407)
        at org.hibernate.engine.spi.SharedSessionContractImplementor.checkOpen(SharedSessionContractImplementor.java:148)
        at org.hibernate.query.internal.AbstractProducedQuery.setParameter(AbstractProducedQuery.java:492)
        at org.hibernate.query.internal.NativeQueryImpl.setParameter(NativeQueryImpl.java:650)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:406)
        at com.sun.proxy.$Proxy67.setParameter(Unknown Source)
        at springtest.TestComponent.doTest(TestComponent.java:21)
        at springtest.Main.main(Main.java:13)
        ... 8 more

When the method is annotated with @Transactional, error does not occur.

Comment From: rafaello7

The sample program: HibernateErrSpring.zip

Comment From: quaff

I think it's designed, you should raise issue to hibernate if insist.

Comment From: rafaello7

Hibernate Session class works correctly. It raises the error because Session.close() was invoked in between by Spring.

The EntityManager injected by Spring for em is not a Hibernate Session/EntityManager, but a proxy created by Spring - com.sun.proxy.$Proxy67 on the stack above. The problem is with the proxy class.

Comment From: snicoll

Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use the issue tracker only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add some more details if you feel this is a genuine bug.

(You can't reuse a query like that)

Comment From: rafaello7

In any way, the Spring framework behaves badly here.

Hibernate by itself does not make any problems with the javax.persistence.Query object reuse. Likewise, I haven't encountered any such problem Java EE environments. Neither in Spring methods marked with @Transactional annotation (also with Propagation.NOT_SUPPORTED). The problem exists only in Spring non-transactional methods.

If it is a desired behavior, attempt to reuse the Query object should be caught by Spring and a Spring exception should inform that query reuse is forbidden instead of propagating the Hibernate error, causing confusion.