我必须保留在 @Transactional Controller 中打开的 ResultSet,以便在 MessageConverter 中使用。为此,我配置了以下内容:
MVC 拦截器:
<mvc:interceptors> <bean class="org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor" p:sessionFactory-ref="sessionFactory"/> </mvc:interceptors>
在 SessionFactory bean 上:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" <property name="hibernateProperties"> <props> <prop key="hibernate.connection.release_mode">on_close</prop> .... </props> </property> </bean>
在 Controller 方法内:
session.doWork((con) -> { con.setHoldability(HOLD_CURSORS_OVER_COMMIT); });
但是PSQLException:此结果集已关闭。
仍然存在。这是 Controller 方法返回时提交事务时日志中的相关片段:
TRACE o.h.e.j.i.JdbcCoordinatorImpl - Registering result set [org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet@5a63c2aa]
DEBUG o.h.e.t.s.AbstractTransactionImpl - committing
TRACE o.h.internal.SessionImpl - Automatically flushing session
TRACE o.h.internal.SessionImpl - before transaction completion
DEBUG o.h.e.t.i.j.JdbcTransaction - committed JDBC Connection
DEBUG o.h.e.t.i.j.JdbcTransaction - re-enabling autocommit
TRACE o.h.e.t.i.TransactionCoordinatorImpl - after transaction completion
TRACE o.h.internal.SessionImpl - after transaction completion
TRACE o.h.internal.SessionImpl - Setting flush mode to: MANUAL
DEBUG o.h.internal.SessionImpl - Disconnecting session
TRACE o.h.e.j.i.JdbcCoordinatorImpl - Releasing JDBC container resources [org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl@97bfa5f]
TRACE o.h.e.j.i.JdbcCoordinatorImpl - Closing result set [org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet@5a63c2aa]
TRACE o.h.e.j.i.JdbcCoordinatorImpl - Closing prepared statement [select...]
DEBUG o.h.e.j.i.LogicalConnectionImpl - Releasing JDBC connection
DEBUG o.h.e.j.i.LogicalConnectionImpl - Released JDBC connection
DEBUG o.h.e.j.s.SqlExceptionHelper - could not advance using next() [n/a] org.postgresql.util.PSQLException: This ResultSet is closed.
我还能做些什么来阻止这种情况发生吗?
最佳答案
默认情况下,Spring 将自行管理 Hibernate session 。正如 HibernateTransactionManager
Javadoc 中所记录的,后果之一是 Spring 将显式调用 session.disconnect()
,这将使您的 connection.release_mode=on_close 失效。
设置。要将此行为更改为 Hibernate 管理的 session ,请务必将 HibernateTransactionManager
上的 hibernateManagedSession
属性设置为 true
:
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:hibernateManagedSession="true" />
这样做必然会扰乱某些采用默认行为的机制。其中之一是通过 TransactionTemplate
进行事务管理:不会自动创建 Hibernate session 。这可以通过将 session 显式绑定(bind)到当前线程来解决,最好在 TransactionTemplate
的子类中捕获:
@Component
public class HibernateTransactionTemplate extends TransactionTemplate
{
@Autowired private SessionFactory sf;
@Autowired @Override public void setTransactionManager(PlatformTransactionManager txm) {
super.setTransactionManager(txm);
}
@Override public <T> T execute(TransactionCallback<T> action) throws TransactionException {
final Session ses = sf.openSession();
TransactionSynchronizationManager.bindResource(sf, new SessionHolder(ses));
try { return super.execute(action); }
finally {
ses.close();
TransactionSynchronizationManager.unbindResource(sf);
}
}
}
关于java - 防止在事务提交时关闭 ResultSet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22735285/