Hibernate提供的操作数据库的方法使用和比较(一)

2014-11-24 18:46:30 · 作者: · 浏览: 5

hibernate对于对象的操作提供了很多的方法,本文简单介绍一下这些方法的使用和比较.


在说明方法之前,说明一下hibernate中的对象的三种状态,transient,persistent,detached.
transient:瞬态或者自由态.
persistent:持久化状态.
detached:脱管状态或者游离态.


状态的判断:


大体上来说,存在于session中的对象为persistent,从session中被clear,evict出来的对象(包括commit是被移出来的对象)是detached.新建的对象和delete的对象是transient状态.但是一个新建的对象的如果有version字段,并且version字段unsaved-value不同,或者在id在由代码赋值的时候有值,则认为是detached状态.


1,persist和save方法:


按照spec,persist不保证立即执行SQL insert语句,save会立即执行insert语句.


在使用过程中,如果记录的id不配置为由代码赋值,如果不为 ,如果对transient或者detached对象的oid赋上值,调用persist方法会有异常:


org.hibernate.PersistentObjectException: detached entity passed to persist:


如果用save方法的话,能够保存成功,赋的oid值不起作用.


如果想要赋的值起作用,用save(Object,ID)的方法.可以用replicate方法做类似的操作.



2,saveOrupdate不是根据数据库有无记录来做save或者update,而是根据对象的状态,如果为transient对象,则save,如果是detached状态,则update.总是会触发hibernate session的save或者update.例如:如果记录的oid不配置为由代码赋值,如果不为 ,如果对这个对象的oid赋了值,Hibernate总是发出一条SQL Update语句,如果数据库没有该oid对应的记录,就不会更新任何记录,如果oid的值为空 的话,会进行save.


如果记录的oid配置为由代码赋值 , ,如果对应该oid的记录不存在 ,就save,如果存在就update.在代码中必须为oid赋值,否则会有异常:org.hibernate.id.IdentifierGenerationException:ids for this class must be manually assigned before calling save():



在同一个session中,对一个transient对象进行saveOrupdate,如果这个对象的oid正好和session中已经存在的对象oid相同,不论对id赋值配置为何种机制,这是候会有异常:


org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:


(上面这条规则同样适用于update方法)



与update的区别是update总是根据对象的oid去update,对于update方法,如果没有设oid会有异常:


org.hibernate.TransientObjectException: The given object has a null identifier:


在一个session中,对delete的obj进行update会有异常,如:


session.delete(obj);


....


session.update(obj);


但是对另一个session中(或者其他程序)delete的对象可以进行update,只是对数据库没有任何改动.




3,merge与update和saveorupdate的区别:从运行是看,最明显的区别是如果update或者saveOrupdae的对象的oid和session中的某个对象相同,会有异常抛出,而merge不会.


如果merge的对象在数据库不存在,会save一条记录(和saveOrupdate类似).


如果session中存在相同oid的实例,会用merge的对象的状态覆盖旧有的持久实例.


Hbtest tbo = new Hbtest();
tbo.setId(new Integer(100));
tbo.setVal("val3");
sessionFactory.getCurrentSession().save(tbo);

Hbtest tbo1 = new Hbtest();
tbo1.setId(new Integer(100));
tbo1.setVal("val5");
sessionFactory.getCurrentSession().merge(tbo1); //update database

System.out.println("******* merge *******" + tbo.getVal()); //tbo的值为val5



如果session没有相应的持久实例,则尝试从数据库中加载或创建一个新的持久化实例,merge方法会返回该持久实例
刚刚merge的这个对象没有被关联到session上,它依旧是游离态的.如果在merge后,对其做改变,值不会反映到数据库.



Hbtest tbo1 = new Hbtest();


sessionFactory.getCurrentSession().merge(tbo1);


...


tbo1.setVal("new val");//不会更新到数据库.


对返回的对象的改动会相应的更新数据库


Hbtest tbo2 = (Hbtest)sessionFactory.getCurrentSession().merge(tbo1);


tbo2.setVal("new val");



可以看出,只有在session中已经存在一个具有相同标识符的持久对象的时候,应该采用merge,此时用saveOrUpdate或者update会报错.如果不确定当前session中是否已经有了具有相同标识符的持久对象,又想将当前的对象更新到(save 或者update)数据库中,可以用merge.



4,replicate()方法完全使用给定对象各个属性的值(包括oid)来持久化给定的游离状态的实体,其中还需要指定存储模式.replicate会先用select看数据是否在数据库已经存在,如果存在,就update,否则save(在存储模式为LATEST_VERSION或者OVERWRITE时).


与save的区别:如果id已经存在,save会有异常(主键冲突,org.hibernate.exception.ConstraintViolationException),在不是由代码指定主键的时候,给save的对象赋的oid不会起作用,而由hibernate配置的机制负责.而replicate会用赋值的oid对数据库进行操作.


与update的区别:比update多执行一条sele