首先来了解下save():
当save(Object)的时候分3种情况:
一,当object是临时状态的时候:
①当id策略为native的时候,当执行save的时候会向数据库发一条insert 语句,并获取id。
②当id为aasiged的时候,save的时候仅仅会持久化,然后commit的时候发出一条Insert 语句。
二,当object是游离对象的时候:
①当id策略为native的时候,当执行save的时候,数据库依然后发出一条insert语句,此时该游离对象的Id被改变了!
②当Id策略为assiged的时候,当执行save的时候,依然还是发出一条inser语句,此时数据库报错,违反唯一约束。
三,当object为持久化对象的时候:
不管id为何种策略,当执行save的时候,不会有任何操作。
总结save()的用法:不管传入的对象是什么状态,都会当作临时对象进行操作(持久化状态就直接返回)。
当update()的时候:
其实处理机制与save差不多,当传入对象是持久化对象的时候,如果持久化没有改变的话,就不会发出Update语句;当传入的是临时和游离状态的对象的时候,
update()都会当作游离对象处理,如果该临时对象没有id值,那么update(object)的时候会理解报错,错误为:org.hibernate.id.IdentifierGenerationException(id策略为assiged),
或者org.hibernate.TransientObjectException(id策略为native),如果该临时对象有带Id,此时该对象会被当作游离对象处理,清理缓存的时候,会向sql发出一条update语句。
这样从save与update,游离对象与临时对象没什么大的区别,只要临时对象有带id值,就完全可以当作游离对象处理!!!
当执行saveOrUpdate()的时候:
当传入对象是持久化对象的时候,执行saveOrUpdate()的操作,直接返回,不会执行什么内容!
下面分两种情况:
一,当传入的对象是游离对象的时候:
①id为native策略:当执行saveOrUpdate(),这个时候会发出如下语句:
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into t_user (name, id) values (?, ?)
Hibernate: update t_user set name=? where id=?
②当id为assiged策略:当执行saveOrUpdate()的时候会发出如下语句:
Hibernate: insert into t_user (name, id) values (?, ?)
Hibernate: select user2x_.id, user2x_.name as name0_ from t_user user2x_ where user2x_.id=?
上面可以看出saveOrUpdate()会先判断对象是否是游离状态还是临时状态,当id为natice策略的时候,很容易就能判断出对象是否是游离对象,但是当id为assiged策略的是时候,就判断不出对象是否是临时的还是游离的,因为assiged下,id都不为null,因此会发出select 语句查出数据库是否有记录来判断是否是游离状态,如果发现是游离状态,就什么也不干,也不会执行save()即insert操作!
二,当传入对象为临时对象的时候:
①id为native策略:当执行saveOrUpdate(),这个时候会发出如下语句:
Hibernate: insert into t_user (name, id) values (?, ?)
②当id为assiged策略:当执行saveOrUpdate()的时候会发出如下语句:
Hibernate: select user2x_.id, user2x_.name as name0_ from t_user user2x_ where user2x_.id=?
Hibernate: insert into t_user (name, id) values (?, ?)
即会查找数据库是否存在该记录,如果有即为游离状态,就会对比该游离对象的属性是否与数据库一致,如果一致就不发update语句,如果不一致,那么就发出update改变某字段的update语句。,如果没,即是确定为临时状态,就执行save操作!!!
总结:在id为native,和assiged,当对象为游离对象的时候,两者情况下,执行的结果不一样,在assiged的条件下,不会有Update操作!,而native的时候,会发出update操作!