Попытка уничтожить бобы в правильном порядке с Spring

У меня есть веб-приложение с 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
6
задан Chris 18 January 2010 в 00:42
поделиться

3 ответа

Похоже, что порядок метода 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
  • Вы не должны Call 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/>
  • Для получения дополнительной информации см. Ссылки выше
4
ответ дан 17 December 2019 в 02:29
поделиться

Вы можете заявить, что HibernateTransaction зависит - на HibernateSessionsion . Поскольку контейнер будет создавать создание бобов в порядке зависимости (запрещать циклические зависимости) и разрывать их в обратном порядке зависимости, это должно сделать трюк.

1
ответ дан 17 December 2019 в 02:29
поделиться

Транзакции должны быть связаны с услугами, если вы следите за пружиной идиомой. Сеансы являются объектами веб-слой, полностью отделены от сервисного уровня. Звучит мне, как будто вы допустили ошибку, запутав свой веб-уровень с сервисным уровнем. Лучше дразнить их; Вы вряд ли будете иметь эту проблему с этой договоренностью.

1
ответ дан 17 December 2019 в 02:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: