Hibernate spring 注释会话未关闭/刷新 [英] Hibernate spring annotation sessions not being closed/flushed

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

问题描述

我继承"了一个项目,该项目使用 Spring 注释来管理 Hibernate 的事务/会话.或者至少它是这样的.目前,Hibernate 会话永远不会被刷新(它们被设置为 FLUSH_MODE_NEVER)并且需要手动刷新 DAO 才能将任何数据写入数据库.

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.

此外,所有 DTO 对象都驻留在休眠的内存中,最终导致 OutOfMemory 错误.

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

我相信我需要告诉 Spring/Hibernate 关闭会话或提交事务.在我的控制器类中,我有处理请求的带注释的方法:

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 {
    ...
    ...
}

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

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

我不仅非常确定配置是错误的,因为没有在每个 DAO 上手动调用刷新,数据不会写入数据库,从日志文件中我们可以看到事务管理器正在刷新和会话关闭已禁用:

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

需要做什么才能使 Spring/hibernate 自动刷新 DAO 和/或关闭会话以防止 Hibernate 使用大量内存?

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?

干杯丹

<!-- 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.

实际问题是您声明的方法@Transactional 是从基类调用的继承方法类,这意味着 Spring 无法拦截对方法并将其包装在事务中.

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 将事务管理作为切面来实现,切面是用代理实现.这样做的限制是,如果一个对象对自身调用一个方法(这是这里发生的事情,因为继承)然后代理看不到调用(因为它发生了在类内部,如调用私有方法),并且不能所以关于它的任何事情.

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 spring 注释会话未关闭/刷新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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