У меня есть веб-приложение с 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>
И вот журнал, который показывает его закрывший сеанс, прежде чем это заключит сделку:
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
Похоже, что порядок метода Destory Calls для неинтефоновых бобов полностью не контролирует. Из документов ( 5.1.4 Использование зависит от зависимости ):
Атрибут зависимости в определении бобов может указать как время инициализации. Зависимость и в случае только синглтона бобов , соответствующее время уничтожения Зависимость
Вы можете создать объект вспомогательного объекта и создание делегирования и разрушение ваших бобов к нему:
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" />
и, в конце концов, возможно, это не лучший способ управлять сеансами и транзакциями в съемках. Рассмотрим использование встроенного встроенного и транзакций и .
Редактировать: Ну, правильный способ управлять транзакциями :
сеанса
и транзакция
beans CreatesSionsess
на заводе сеанса, возвращенные org.springframework.orm.hibernate3.annotation.annotationsessionSactoryBean
. Вы можете ввести эту сессию завода в свои бобы и звонить GetCurrentsion
, когда вам нужен сеанс, A это будет работать нормально. @transactional
аннотации на транзакционные методы). Чтобы сделать его работу, вы должны добавить к вашему конфигурации: .
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="hibernateSessionFactory"/>
</bean>
<tx:annotation-driven/>
Вы можете заявить, что HibernateTransaction
зависит - на HibernateSessionsion
. Поскольку контейнер будет создавать создание бобов в порядке зависимости (запрещать циклические зависимости) и разрывать их в обратном порядке зависимости, это должно сделать трюк.
Транзакции должны быть связаны с услугами, если вы следите за пружиной идиомой. Сеансы являются объектами веб-слой, полностью отделены от сервисного уровня. Звучит мне, как будто вы допустили ошибку, запутав свой веб-уровень с сервисным уровнем. Лучше дразнить их; Вы вряд ли будете иметь эту проблему с этой договоренностью.