Hibernate的春天注解会话不关闭/刷新 [英] Hibernate spring annotation sessions not being closed/flushed

查看:143
本文介绍了Hibernate的春天注解会话不关闭/刷新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经继承它使用Spring注解管理与Hibernate事务/会话的项目。或者至少它的意思是。目前休眠会话从未得到冲洗(它们被设置为FLUSH_MODE_NEVER)和DAO的需要手工冲洗的任何数据被写入到数据库中。

此外所有的DTO对象驻留在休眠的记忆,最终导致一个OutOfMemory错误。

我相信我要告诉春/休眠关闭会话或提交事务。在我的控制器类我有处理请求注解的方法:

  @Transactional(传播= Propagation.REQUIRED,的rollbackFor = Exception.class)
公众的ModelAndView的handleRequest(HttpServletRequest的请求,HttpServletResponse的响应)抛出异常{
    ...
    ...
}

和在applicationContetxt.xml文件,我相信我的设置休眠事务管理器,并告诉Spring使用注释:

 <! -  Hibernate3的事务管理器 - >
<豆的id =transactionManagerLocal级=org.springframework.orm.hibernate3.HibernateTransactionManager>
    <属性名=数据源REF =$ {} local.data.source/>
    <属性名=SessionFactory的REF =的LocalSessionFactory/>
< /豆><! - 标定使用@Transactional注解 - >
< TX:注解驱动的事务管理器=transactionManagerLocal命令=200/>

我不仅pretty确保配置是错了的数据不被写入到数据库,而无需手动调用flush对每个DAO的方式,从日志文件中我们可以看到,事务管理器它的冲洗和会议闭幕禁用:

  INFO [HTTP-8080-2] TransactionFactoryFactory  - 交易策略:org.springframework.orm.hibernate3.SpringTransactionFactory
INFO [HTTP-8080-2] TransactionManagerLookupFactory - 无的TransactionManagerLookup配置(在JTA环境中,不建议使用读写或交易二级缓存)
INFO [HTTP-8080-2] SettingsFactory - 自动冲洗beforeCompletion中(中):禁用
INFO [HTTP-8080-2] SettingsFactory - 自动会话关闭在交易结束:禁用

需要采取哪些措施使春/ Hibernate会自动刷新的DAO和/或关闭会话prevent大量内存正在使用Hibernate的?

欢呼

 <! -  MySQL的/ InnoDB的会话工厂 - >
<豆ID =的LocalSessionFactory级=org.springframework.orm.hibernate3.LocalSessionFactoryBean>
    <属性名=数据源REF =$ {} local.data.source/>
    <属性名=mappingResources>
        <列表>
            < VALUE>净利润/公司/项目名称/域/ ExchangeRate.hbm.xml< /值>
            <! - 其他 - >        < /列表>
    < /性>   <属性名=hibernateProperties>
        <道具及GT;
            <支撑键=hibernate.dialect> org.hibernate.dialect.MySQLInnoDBDialect< /道具>
            <支撑键=在hibernate.cache.provider_class> org.hibernate.cache.NoCacheProvider< /道具>
            <支撑键=hibernate.connection.zeroDateTimeBehavior> convertToNull< /道具>
            <! -
            什么也没做
            <支撑键=hibernate.transaction.flush_before_completion>真< /道具>
            <支撑键=hibernate.transaction.auto_close_session>真< /道具>
             - >
        < /道具>
    < /性>
< /豆><! - Hibernate3的事务管理器 - >
<豆的id =transactionManagerLocal级=org.springframework.orm.hibernate3.HibernateTransactionManager>
    <属性名=数据源REF =$ {} local.data.source/>
    <属性名=SessionFactory的REF =的LocalSessionFactory/>
< /豆>
<! - 标定使用@Transactional注解 - >
< TX:注解驱动的事务管理器=transactionManagerLocal命令=200/><豆的id =exchangeRateDAO级=net.company.project.dao.hibernate.impl.ExchangeRateDAOImpl>
     <属性名=SessionFactory的REF =的LocalSessionFactory/>
 < /豆>


解决方案

我的一个聪明的同事发现了什么问题。


  

实际的问题是,你已经声明为方法
  @Transactional是继承的方法是从一个被称为基地
  类,这意味着春天是无法拦截到的调用
  方法和事务中的包裹。


  
  

春季实现事务管理的方面,并且方面
  与代理实现的。这样做的限制是,如果对象
  调用自身的方法(这是发生了什么事,因为在这里
  继承),那么代理不看到调用(因为它发生
  其内部的类,比如调用私有方法),而不能
  所以任何事情。


这是有道理的,但似乎因为它失败没有任何错误信息或警告写入任何数据是难以置信的危险。

I've 'inherited' a project which uses Spring annotations to manage transactions/sessions with Hibernate. Or at least it's meant to be. Currently the Hibernate sessions never get flushed (they are set to FLUSH_MODE_NEVER) and the DAO's need to be flushed by hand for any data to be written to the database.

Also all the DTO objects stay resident in hibernate's memory, eventually leading to an OutOfMemory error.

I believe I need to tell Spring/Hibernate to close the session or commit the transaction. In my controller class I have the annotated method for handling the requests:

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

and in the applicationContetxt.xml file I believe I setup the hibernate transaction manager and tell spring to use the annotations:

<!-- 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" />

Not only am I pretty sure that the config is wrong by the way data doesn't get written to the DB without manually calling flush on each of the DAO's, from the log file we can see that transaction manager has it's flushing and session closing disabled:

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

What needs to be done to make Spring/hibernate automatically flush the DAOs and/or close the session to prevent huge amounts of memory being used by Hibernate?

cheers 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>     

解决方案

One of my cleverer colleagues discovered what the problem was.

The actual problem was that the method that you've declared as @Transactional is an inherited method that is called from a base class, which means that Spring is unable to intercept calls to the method and wrap it in a transaction.

Spring implements transaction management as aspects, and aspects are implemented with proxies. The limitation of this is that if an object calls a method on itself (which is what's happening here because of inheritance) then the proxy doesn't see the call (because it happens internally within the class, like calling a private method), and can't so anything about it.

Which makes sense but seems to be incredibly dangerous as it fails to write any data without any error message or warning.

这篇关于Hibernate的春天注解会话不关闭/刷新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆