Hibernate весенние сессии аннотации не закрываются / сбрасываются - PullRequest
2 голосов
/ 31 января 2012

Я «унаследовал» проект, который использует аннотации Spring для управления транзакциями / сеансами в Hibernate. Или, по крайней мере, так и должно быть. В настоящее время сеансы Hibernate никогда не сбрасываются (они установлены на FLUSH_MODE_NEVER), и DAO необходимо очищать вручную для любых данных, которые будут записаны в базу данных.

Также все объекты DTO остаются в памяти гибернации, что в конечном итоге приводит к ошибке OutOfMemory.

Мне кажется, мне нужно сказать Spring / Hibernate закрыть сеанс или зафиксировать транзакцию. В моем классе контроллера у меня есть аннотированный метод для обработки запросов:

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
    ...
    ...
}

и в файле applicationContetxt.xml я полагаю, что настроил диспетчер транзакций гибернации и приказал Spring использовать аннотации:

<!-- hibernate3 transaction manager -->
<bean id="transactionManagerLocal" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="dataSource" ref="${local.data.source}" />
    <property name="sessionFactory" ref="localSessionFactory" />
</bean>

<!-- Demarcate using @Transactional annotation -->
<tx:annotation-driven transaction-manager="transactionManagerLocal" order="200" />

Мало того, что я почти уверен, что конфигурация неверна из-за того, что данные не записываются в БД без ручного вызова сброса на каждом из DAO, из файла журнала мы видим, что диспетчер транзакций сбрасывает и закрытие сессии отключено:

INFO  [http-8080-2] TransactionFactoryFactory - Transaction strategy: org.springframework.orm.hibernate3.SpringTransactionFactory
INFO  [http-8080-2] TransactionManagerLookupFactory - No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
INFO  [http-8080-2] SettingsFactory - Automatic flush during beforeCompletion(): disabled
INFO  [http-8080-2] SettingsFactory - Automatic session close at end of transaction: disabled

Что необходимо сделать, чтобы Spring / hibernate автоматически очищал DAO и / или закрывал сеанс, чтобы предотвратить использование Hibernate огромных объемов памяти?

веселит Dan

<!-- MySQL/InnoDB session factory -->
<bean id="localSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="${local.data.source}"/>
    <property name="mappingResources">
        <list>
            <value>net/company/projectname/domain/ExchangeRate.hbm.xml</value>
            <!-- Other  -->

        </list>
    </property>

   <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
            <prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
            <prop key="hibernate.connection.zeroDateTimeBehavior">convertToNull</prop>
            <!-- 
            DOES NOTHING
            <prop key="hibernate.transaction.flush_before_completion">true</prop>
            <prop key="hibernate.transaction.auto_close_session">true</prop>
            -->
        </props>
    </property>
</bean>

<!-- hibernate3 transaction manager -->
<bean id="transactionManagerLocal" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="dataSource" ref="${local.data.source}" />
    <property name="sessionFactory" ref="localSessionFactory" />
</bean>


<!-- Demarcate using @Transactional annotation -->
<tx:annotation-driven transaction-manager="transactionManagerLocal" order="200" />

<bean id="exchangeRateDAO" class="net.company.project.dao.hibernate.impl.ExchangeRateDAOImpl">
     <property name="sessionFactory" ref="localSessionFactory"/>
 </bean>     

Ответы [ 4 ]

5 голосов
/ 30 мая 2012

Один из моих умных коллег обнаружил, в чем проблема.

Фактическая проблема заключалась в том, что метод, который вы объявили как @Transactional - это унаследованный метод, который вызывается из базы. класс, что означает, что Spring не может перехватывать вызовы метод и обернуть его в транзакции.

Spring реализует управление транзакциями как аспекты, а аспекты реализовано с прокси. Ограничением этого является то, что если объект вызывает метод сам по себе (что происходит здесь из-за наследование), то прокси не видит вызов (потому что это происходит внутри класса, например, вызов частного метода), и не может так что-нибудь об этом.

Это имеет смысл, но кажется невероятно опасным, поскольку не в состоянии записать какие-либо данные без какого-либо сообщения об ошибке или предупреждения.

2 голосов
/ 12 ноября 2012

есть другой способ вместо шаблона hibernate (шаблон hibernate будет связывать переход весны в hibernate, поэтому в Spring 3.1 он устарел), ключом к решению этой проблемы является удаление любой конфигурации для hibernate, кроме dialct и url вПростой способ: удалите транзакционный материал из ваших свойств гибернации, так как вы хотите, чтобы Spring управлял транзакциями, а не гибернацией.как упоминал Мартен Дейнм в этом URL http://forum.springsource.org/archive/index.php/t-47667.html, здесь приведен фрагмент моего весеннего XML-файла конфигурации

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="configLocation">    
        <value>
            classpath:/com/spring/hibernate.cfg.xml
        </value>
    </property>       
    </bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

, а здесь находится файл гибернации

<session-factory> 
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>

<mapping resource="com/spring/BloodType.hbm.xml" />
</session-factory>

, не забудьтечтобы написать @Transactional в вашем методе или классе, также используйте

Session session = sessionFactory.getCurrentSession();

, и этот

BloodType b = new BloodType();
b.setId(new Long(1));
BloodType b1 = (BloodType)session.get(BloodType.class, 12L);
session.delete(b1);
session.save(b);

будет работать прекрасно, без необходимости session.flush() или transaction.commit() надеюсь, что это работает

1 голос
/ 11 ноября 2012

с помощью шаблона hibernate решает его

@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
       hibernateTemplate = new HibernateTemplate(sessionFactory);
}

, а затем использует шаблон, как в этой ссылке http://singgihpraditya.wordpress.com/2010/02/13/spring-3-0-and-hibernate-tutorial-part-1/

Ваш ответ будет здорово поделиться

0 голосов
/ 31 января 2012

Если транзакция (которая аннотирована) завершается успешно, автоматически вызывается transaction.commit(), который записывает содержимое в БД. Проверьте, вызывается ли транзакция и не выдается ли исключений.

также убедитесь, что вы связываете свою сессионную фабрику с объявленным транскейшированием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...