gpt4 book ai didi

java - 尝试使用 Spring 以正确的顺序销毁 bean

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:15:36 27 4
gpt4 key购买 nike

我有一个带有 Spring 的 Web 应用程序,它设置为创建我的 hibernate session 工厂(单例)以及 session 和事务(两者都是请求范围的),但它以错误的顺序破坏了 session 和事务。我如何配置它以便在 session 之前销毁事务?这是我的 spring applicationContext.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="hibernateSessionFactory" scope="singleton"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>

<!-- The per-http request hibernate session -->
<bean id="hibernateSession" factory-bean="hibernateSessionFactory"
factory-method="openSession" destroy-method="close" scope="request" />

<!-- The per-http request transaction (i need this to be destroyed BEFORE the session) -->
<bean id="hibernateTransaction" factory-bean="hibernateSession"
factory-method="beginTransaction" destroy-method="commit" scope="request" />
</beans>

这是显示它在关闭事务之前关闭 session 的日志:

16111 [http-8080-3] DEBUG org.springframework.beans.factory.support.DisposableBeanAdapter  - Invoking destroy method 'close' on bean with name 'hibernateSession'
16111 [http-8080-3] DEBUG org.hibernate.jdbc.ConnectionManager - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
16111 [http-8080-3] DEBUG com.mchange.v2.resourcepool.BasicResourcePool - trace com.mchange.v2.resourcepool.BasicResourcePool@17e4dee [managed: 4, unused: 3, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@19a8416)
16111 [http-8080-3] DEBUG org.springframework.beans.factory.support.DisposableBeanAdapter - Invoking destroy method 'commit' on bean with name 'hibernateTransaction'
16111 [http-8080-3] DEBUG org.hibernate.transaction.JDBCTransaction - commit
16111 [http-8080-3] WARN org.springframework.beans.factory.support.DisposableBeanAdapter - Invocation of destroy method 'commit' failed on bean with name 'hibernateTransaction'
org.hibernate.SessionException: Session is closed

最佳答案

对于非单例范围的bean,destory 方法调用的顺序似乎完全失控了。来自文档(5.1.4 Using depends-on):

The depends-on attribute in the bean definition can specify both an initialization time dependency and, in the case of singleton beans only, a corresponding destroy time dependency

您可以创建一个辅助对象并将 bean 的创建和销毁委托(delegate)给它:

public class HelperObject
{
private SessionFactory factory;
private Session session;
private Transaction tx;

public void init()
{
session = factory.createSession();
tx = session.beginTransaction();
}

public void destroy()
{
tx.commit();
session.close();
}

...
}

--

<bean id = "helperObject" class = "HelperObject" scope = "request" init-method = "init" destroy-method = "destroy">
<property name = "factory" ref = "hibernateSessionFactory" />
</bean>

<bean id="hibernateSession" factory-bean="helperObject"
factory-method="getSession" scope="request" />

<bean id="hibernateTransaction" factory-bean="helperObject"
factory-method="getTransaction" scope="request" />

而且,毕竟,这可能不是在 Spring 中管理 Hibernate session 和事务的最佳方式。考虑使用 Spring 的内置 Hibernatetransactions支持。

编辑:那么,管理事务的正确方法:

  • 您不需要请求范围的 sessiontransaction bean
  • 您不应在 org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean 返回的 session 工厂上调用 createSession。您可以将此 session 工厂注入(inject)到您的 bean 中,并在需要 session 时调用 getCurrentSession,它会正常工作。
  • 您可以使用声明式事务管理(事务方法上的@Transactional 注释)。为了让它工作,你应该添加到你的配置中:

.

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="hibernateSessionFactory"/>
</bean>

<tx:annotation-driven/>
  • 有关详细信息,请参阅上面的链接

关于java - 尝试使用 Spring 以正确的顺序销毁 bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2083289/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com