您的位置:首页 > 编程语言 > Java开发

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

2016-05-03 14:35 627 查看
         刚开始写博客,其中有何纰漏请包涵一二。

    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的理解,如有偏差,还望指正。

 

   

       

         

       

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hibernate spring