您的位置:首页 > 其它

初学hibernate,快照更新是一个什么机制.

2017-04-18 00:44 387 查看
  

Transaction transaction= MySessionFactory.session().beginTransaction();
User user=null;
try{
//here must invoke dao's getAllById because of use another transaction environment
User u2=new UserDao().getAllById(user.getId());
//second set value to selected object
u2.setName(user.getName());
u2.setPassword(user.getPassword());
u2.setTelephone(user.getTelephone());
u2.setIsAdmin(user.getIsAdmin());
u2.setUsername(user.getUsername());

transaction.commit();
}catch(Exception e){
e.printStackTrace();
transaction.rollback();


  

  上面代码是指在一个事务环境下(getCurrentSession())根据id查询user表中所有字段,只是多了对查出来的对象赋值操作,但正是这个操作,使得hb更新了set过的属性.为什么会这样呢?

  其实很简单,当你在进行查询操作时,返回的对象hb会对他进行一个snapshot,即快照,那么,当你提交事务时(查询也需要在事务环境下,因为使用currentSession),如果你set了新值,那么hb会对set过的属性进行更新操作,如果你开启动态方法更新,即dynamic-update="true",那么只会对产生变化的属性进行更新操作

  那么利用这hb这个特性,可以做点什么呢?看下面的代码

//id首先检索出数据库中对应的行对象user,其他updateUser非null属性为你需要set到user中
public void updateByUpdateUser(User updateUser) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//first get snapshot 先通过id select所有字段
User user=getAllById(updateUser.getId());
//second get all getter method excluded null value 提取出声明的方法
Method[] methods=updateUser.getClass().getDeclaredMethods(); //get own declared methods
for(Method method:methods){
String methodName=method.getName();
        //找到get方法
if( methodName.matches("get[A-Z].*") ){
        //获得get方法返回值
Object value=method.invoke(updateUser); //from updateUser
//如果不为null,就表示需要更新这个字段
          if(value!=null){ //get not null property
String setter=methodName.replace("get","set");
            //反射出setter,因为反射一个方法需要方法名加参数类型,但是这里我只有get的返回值,没有确切的类型,所以直接使用了value.getClass()来获得参数类型,不是很准确.如果真实类型是父类,就找不到这个方法了
Method setterMethod=User.class.getDeclaredMethod(setter,value.getClass());  //value.getClass()找到这个填充参数的值,如果真实参数为父类,就不准确了.不过在javaBean中一般不会使用父类参数
setterMethod.invoke(user,value);
}
}


  这里我可以写一个方法,只需要一个user对象,其实就是模拟上面原理,通过反射,动态给快照对象赋值,那么就能达到指定更新属性的目的了,不过还是需要在事务环境中,同时是通过这个user的id先找到快照,然后对其他属性进行判断,如果非null,就表示我需要更新这个字段,而且,只需要传递一个user对象即可,这不是很好解决了动态更新么

  其实上面的代码就是hb中merge()方法的update的原理


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