避免 Hibernate 中用get/load方法获取的实体调用set方法后自动更新

一、问题症状描述

      最近在处理一个新需求问题,代码的大体逻辑是获取一个实体对象,调用该对象的set方法设置其中的某些字段,而后把修改后的实体做为参数供其余地方调用,根据返回值来决定是否更新这个实体到数据库中。数据库

      按照这个思路调用了系统中的getByid方法,结果测试的时候发现,无论返回值是什么,这个实体最终都被更新到数据库中了。好吧,这明显是有问题的....【没有问题的代码不是好代码 - -|| 】session

二、问题缘由分析和解决办法

        2.1  查看日志信息后发现,系统老是会打印出一个update语句。说明系统的确是执行了更新操做的,可是我并无调用任何和update相关的方法。测试

        2.2  跟踪代码发现,getById方法实际上是调用了hibernate的get方法。嗯,果真,问题出在这里了.....spa

        2.3  Hibernate的get和load方法查询出的实体都是持久化对象,拿到该对象后,若是你调用了该对象的set方法,那么在事务递交的时候,Hibernate会把你设置的值自动更新到数据库中。.net

    解决办法:hibernate

        在获取实体对象后,调用下getHibernateTemplate().evict(entity)方法,该方法的做用是把持久化对象变成托管状态。变成托管状态后,Hibernate就不会再去自动更新该实体。日志

三、相关知识扩展

Hibernate的几种实体状态:对象

1.瞬态:
  一个实体经过new操做符建立后,没有和Hibernate的Session创建关系,也没有手动赋值过该实体的持久化标识(持久化标识能够认为是映射表的主键)。
               此时该实体中任何属性的更新都不会反映到数据库表中。
2.持久化:
               当一个实体和Hibernate的Session建立了关系,并获取了持久化标识,并且在Hibernate的Session生命周期内存在。
               此时针对该实体任何属性的更改都会直接影响到数据库表中一条记录对应字段的更新,即与数据库表同步。
3.脱管:
              当一个实体和Hibernate的Session建立了关系,并获取了持久化标识,而此时Hibernate的Session生命周期结束,实体的持久化标识没有被改动过。
              针对该实体任何属性的修改都不会及时反映到数据库表中。blog

              关闭session可使实体从持久化状态转为托管状态。生命周期

知识扩展部分参考自 http://blog.csdn.net/sunhuwh/article/details/9183539 ,感谢做者。


转帖请注明文章来源: http://blog.csdn.net/yang_lover/article/details/45057181