您的位置:首页 > 其它

Hibernate框架学习(第四讲)---持久化对象状态

2016-12-28 15:39 260 查看
之前文章中我们提到过持久化定义时,提及到瞬时状态和持久化状态。而一个持久化示例可能存在的状态有三种:

瞬时状态:

该实例是刚用new语句创建的,还没有被持久化,不处于任何Session的缓存中。它没有持久化标识(相当于主键值)。处于瞬时状态的实例被称为瞬时对象。它的特点是:

不和任何一个Session实例关联。在数据库中没有对应的记录。

持久化(persistent)状态:

已经被持久化,加入到Session缓存中。处于持久化状态的实例被称为持久化对象。

实例目前与某个Session有关联。 它拥有持久化标识(相当于主键值),并且可能在数据库中有一个对应的行。 Hibernate保证在同一个Sesion实例的缓存中,数据库中的每条记录只对应唯一的持久化对象。 它的特点是:

持久化对象总是被一个Session实例关联。持久化对象和数据库中的相关记录对应。Session在清理缓存时,会根据持久化对象的属性变化,来同步更新数据库。

脱管(detached)状态:

已经被持久化过,但不再处于Session的缓存中。处于脱管状态的实例被称为脱管对象。实例曾经与某个持久化上下文发生过关联,不过那个上下文被关闭了, 或者这个实例是被序列化(serialize)到另外的进程。 它拥有持久化标识,并且在数据库中可能存在一个对应的行。 对于脱管状态的实例,Hibernate不保证任何持久化标识和Java标识的关系。它的特点是:

不再位于session的缓存中,即它不再和session关联。它拥有持久化标识。

Session的saveOrUpdate()方法:

Session的save()方法:使用一个临时对象转变为持久对象。

方法签名:public Serializable save(Object object) throws HibernateException; 它完成以下操作:

1) 把持久化类的实例加入到缓存中,使它变为持久化对象。

2) 选用映射文件指定的标识符生成器为持久化对象分配唯一的OID。

3) 计划执行一个insert语句,把持久化对象当前的属性值组装到insert 语句(SQL DML)中。值得注意的是,save()方法并不是立即执行SQL insert语句。只有当Session清理缓存时,才会执行SQL insert语句。

另外,需要注意的是:Hibernate通过持久化对象的OID来维持它和数据库相关记录的对应关系。所以当持久化的实例处于持久化状态时,不允许程序随意修改它的OID。其实,无论java对象处于瞬时状态、持久化状态还是脱管状态,程序都不应该修改它的OID。

Session的update()方法:使一个脱管对象转变为持久化对象。

方法签名:public void update(Object object) throws HibernateException; 它完成以下操作:

1) 把脱管对象重新加入到Session缓存中,使它变为持久化对象。

2) 计划执行一个update语句。值得注意的是,Session只有在清理缓存的时候才会执行update语句,并且在执行时才会把持久化对象当前的属性值组装到update语句中。

Session的saveOrUpdate()方法:

方法签名:public void saveOrUpdate(Object object) throws HibernateException ; saveOrUpdate()方法同时包含了save()与update()方法的功能,如果传入的参数是瞬时对象,就调用save()方法;如果传入的参数是脱管对象,就调用update()方法;如果传入的参数是持久化对象,方法就直接返回。那么,saveOrUpdate()方法如果判断一个对象处于瞬时状态不是脱管状态呢?如果满足以下情况之一,Hibernate就把它作为临时对象:

1) Java对象的OID取值为null。

2) Java对象具有version属性,并且取值了null。

3) 在映射文件中为元素设置了unsaved-value属性,并且OID取值与unsaved-value属性值匹配。

4) 在映射文件中为元素设置了unsaved-value属性,并且version属性取值与unsaved-value属性值匹配。

5) 自定义了Hibernate的Interceptor实现类,并且Interceptor的isUnsaved()方法返回Boolean.TRUE。

Session的delete()方法:

方法签名:public void delete(Object object) throws HibernateException; delete()方法用于从数据库中删除与Java对象对应的记录。如果传入的参数是持久化对象,Session就计划执行一个delete语句。如果传入的参数是游离对象,先使游离对象被Session关联,使它变为持久化对象,然后计划执行一个delete语句。值得注意的也是,Session只有在清理缓存的时候才会执行delete语句。

Query接口

使用 “?”按参数位置绑定:

通过Query接口执行HQL语句时,可以先设定查询参数,然后通过setXXX()方法来绑定参数。如下

Query query = session.createQuery("from User as u where u.age > ? and u.name like ?");
query.setInteger(0, 25);
query.setString(1, "%a%");
List list = query.list();


Hibernate提供了绑定各种类型的参数的方法,如参数为字符串类型,可调用setString(),如果参数为整数类型,可调用setInteger()方法,以此类推。这些setXXX()方法的第1个参数HQL查询语句中参数的位置,第2个参数代表HQL查询语句中参数的值。

使用 “:” 后跟变量名来按命名参数绑定:

可以使用命名参数来取代使用“?”设置参数的方法,这可以不用依照特定的顺序来设定参数值,如上例可改成:

Query query = session.createQuery(“from User as u where u.age > :minAge and u.name like likeName”);

query.setInteger(“minAge”, 25);

query.setString(“likeName”, “%a%”);

List list = query.list();

使用命名参数方式的绑定方式有以下优势:

1) 代码可读性更好。

2) 命名参数不依赖它们在查询字符串中出现的位置。

3) 在同一个查询中可以多次使用。

所以,应该优先考虑使用命名参数方式。

使用命名查询(nameQuery):

可以将HQL语句编写在程序之外,以避免硬编码在程序之中,这样要修改HQL语句时就很方便。在xxx.hbm.xml中使用标签,并在

Query query = session.getNamedQuery("queryUserByAgeAndName");
query.setInteger("minAge", 25);
query.setString("likeName", "%a%");
List list = query.list();


Query接口的list()方法:

Query接口的list()方法用于取得一个List类的实例,此实例中包括的可能是一个对象集合,也可能是一个对象数组集合。最常见的使用是用list()方法来取得一组符合实例对象。如上示例。

Query接口的uniqueResult()方法:

当确信使用的HQL语句查询时返回的集合中只有一个对象时,就可以使用这个方法。但如果返回结果中有多个对象,使用这个方法会抛出
org.hibernate.NonUniqueResultException 异常,说“query did not return a unique result”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hibernate