关于Hibernate与spring集成更新无效的分析
来源:互联网 发布:手机淘宝代付在哪里 编辑:程序博客网 时间:2024/05/19 14:51
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事务管理的事。
情况一:
测试代码:
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集成更新无效的分析
- JPA/Hibernate与Spring集成的事务分析
- spring与hibernate集成--关于配置文件的最优化使用
- spring与hibernate的集成
- spring与hibernate的集成
- 关于spring+struts+hibernate集成的问题
- spring与hibernate集成
- Spring与Hibernate集成
- Spring与Hibernate的无缝集成
- spring与带Annotation的hibernate集成
- spring与带Annotation的hibernate集成
- Spring集成的Hibernate编码与测试
- spring与struts、hibernate的集成
- dorado与Struts、Hibernate、Spring的集成
- dwr与spring集成的错误分析
- 关于spring与EHcache的集成
- spring与hibernate集成--spring配置文件applicationContext.xml的配置:
- Spring与JPA(Hibernate)集成
- vim编译器之神的基本命令
- 『Python』序列学习总结之六——如何命名规范的变量名
- 【HUSTOJ】1011: 行李托运
- 符号位为1的二进制转十进制负数
- D:\miles28370\miles28370\application\core\build.xml:18: Compile failed; see the compiler error outpu
- 关于Hibernate与spring集成更新无效的分析
- hibernate 的级联操作 cascade操作
- Leetcode 260
- web截屏功能的实现
- jsp
- 关于ArrayList的5道面试题
- Elasticsearch基础教程
- java流
- AsyncTask 异步任务类的使用方法