关于Hibernate与spring集成更新无效的分析

         刚开始写博客,其中有何纰漏请包涵一二。

    Hibernate是一个ORM持久化框架,也是主流的ORM框架之一。使用它,程序员能够利用OOP思想操作数据库数据。但是新手刚开始学习Hibernate的时候,由于对于Hibernate的工作原理和机制理解不透彻,在使用过程中,将会遇到许多问题和掉入许多深坑(好几天出不来,比如楼主我,唉~~~~),大大的降低了工作效率。最近使用Hibernte做个人项目时,又掉进了深坑,为了避免更多小白入坑难以自拔,就有了楼楼这篇漏作。
    在使用Hibernate的时候,使用框架的接口方法,能够简化开发代码,楼楼在做个人项目时为了省点时间撸,就想尝试使用Hibernate的接口方法,像什么save()、delete()、update()、saveorUpdate()的,不过确实很方便。在使用过程中就遇到问题,就行update()更新无效,数据更新不完全等等。
    一、 使用Update更新数据无效。
    在调用update方法更新数据时,更新操作无效,也不抛出任何异常。楼楼复习了hibernate知识和查阅了相关资料,并经过了自身测试,找到了问题所在。
    在使用Hibernate与spring集成时,将Hibernate事务交给spring管理。配置文件如:

    
   
 <!-- 定义事务 -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 配置详细的事务定义 -->
        <tx:attributes>
            <!-- 所有以查询数据库的方法是read-only的 -->
            <tx:method name="get*" propagation="REQUIRED" read-only="true" />
            <tx:method name="find*" propagation="REQUIRED" read-only="true" />
            <tx:method name="list*" propagation="REQUIRED" read-only="true" />
            <!-- 其他方法使用默认的事务设置 -->
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut expression="execution(* com.hal.bms..*.services..*.*Services.*(..))"
            id="allpoint" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="allpoint" />
    </aop:config>


在配置文件中,配置了事务管理的,其他方法调用不存在任何问题,但是update方法却出了问题。也就是说并不是spring事务管理的事。

    情况一:

    在使用update的时候,更新的是缓存中的数据,并不会立马同步到数据库中,如果想立即更新数据库数据,就可以使用session.flush()方法。我们来测试一下吧:
        测试代码:
    
        public  void  updateSelf(User user){
      System.out.println("进入本方法!");
      getSession().update(user);
      getSession().flush();
 }

         注意图片中的第四条数据,待会就是测试这条了。


     

        然后将用户的地址改为“中国北京”,看看测试结果。

测试成功。说明更新无效是由于只更新了缓存中的数据,如果不调用flush,则数据库并不会更新。

能成功的前提是因为在web.xml配置了OSIV

	<!-- Hibeinate OSIV 配置 -->
	<filter>
		<filter-name>OpenSessionInViewFilter</filter-name>
		<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
        <init-param>
			<param-name>FlushMode</param-name>
			<param-value>AUTO</param-value>
		</init-param> 
	</filter>
	<filter-mapping>
		<filter-name>OpenSessionInViewFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

  情况二:

   就是情况一下面要说的FlushMode属性,该属性有五中状态(这个网上一查就知道了),分别是:

1、NEVEL:被MANUAL取代了 
2 MANUAL: 
如果FlushMode是MANUAL或NEVEL,在操作过程中hibernate会将事务设置为readonly,所以在增加、删除或修改操作过程中会出现如下错误 
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition; 
解决办法:配置事务,spring会读取事务中的各种配置来覆盖hibernate的session中的FlushMode; 
3 AUTO 
设置成auto之后,当程序进行查询、提交事务或者调用session.flush()的时候,都会使缓存和数据库进行同步,也就是刷新数据库 
4 COMMIT 
提交事务或者session.flush()时,刷新数据库;查询不刷新 
5 ALWAYS: 
每次进行查询、提交事务、session.flush()的时候都会刷数据库 
ALWAYS和AUTO的区别:当hibernate缓存中的对象被改动之后,会被标记为脏数据(即与数据库不同步了)。当 session设置为FlushMode.AUTO时,hibernate在进行查询的时候会判断缓存中的数据是否为脏数据,是则刷数据库,不是则不刷,而always是直接刷新,不进行任何判断。很显然auto比always要高效得多。


所以如果没有配置OSIV,就需要自己手动设置FlushMode属性:session.setFlushMode(FlushMode.xxx)。


情况三:就是事务并没有管理update的类或方法,这时就需要自己手动添加事务管理。在方法上添加事务注解属性@Transactional。然后参考情况一二。


以上属个人对于Hibernate的理解,如有偏差,还望指正。





 

   


       
         
       
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值