操纵持久化对象
++YONG原创,转载请注明
1. 理解Session的缓存:
在Java里面,缓存通常是指Java对象的属性占用的内存空间,通常是一些集合类型的属性。在session接口的实现类SessionImpl中定义了一系列的Java集合,这些Java集合就构成了Session的缓存。
当Session的save()方法持久化一个对象时,这个对象被加入到Session的缓存中,以后即使应用程序中的引用变量不再引用这个对象,只要Session的缓存还没有被清空,这个对象仍然处于生命周期中。当Session的load()方法加载一个对象时,Session会先判断缓存中是否已经存在这个对象了,如果存在,就不需要再到数据库中重新加载了。
Session的缓存有两大作用:
1.1. 减少访问数据库的频率。
1.2. 保证缓存中的对象与数据库中的相关记录保持同步。
Session有两个方法:一个commit()事务提交方法,还有flush()刷新缓存方法,都有着清理缓存的作用。flush()进行缓存的清理,执行一系列的SQL语句,但不会提交事务。而commit()方法会先调用flush()方法,然后在提交事务。
2. 定义持久化类的建议:
在应用程序中,用来实现业务问题实体的(如,在电子商务应用程序中的Customer和Order) 类就是持久化类。如果这些持久化类遵循一些简单的规则,Hibernate能够工作得更好,这些规则也被称作简单传统Java对象(POJO:Plain Old Java Object)编程模型。但是这些规则并不是必需的。最好要遵循以下几条主要的规则:
1) 实现一个默认的(即无参数的)构造方法(constructor):
我们强烈建议,在Hibernate中,为了运行期代理的生成,构造方法至少是 包(package)内可见的。
2) 提供一个标识属性(identifier property):
我们建议你对持久化类声明命名一致的标识属性。我们还建议你使用一个可以为空(也就是说,不是原始类型)的类型。
3) 使用非final的类:
代理(proxies)是Hibernate的一个重要的功能,它依赖的条件是,持久 化类或者是非final的,或者是实现了一个所有方法都声明为public的接口。你也应该避免在非final类中声明 public final
的方法。
4) 为持久化字段声明访问器(accessors):
5) 如果你有如下需求,你必须重载 equals() 和 hashCode()方法:
l 想把持久类的实例放入Set中(当表示多值关联时,推荐这么做)
l 想重用脱管实例
Hibernate保证,仅在特定会话范围内,持久化标识(数据库的行)和Java标识是等价的。因此,一旦 我们混合了从不同会话中获取的实例,如果希望Set有明确的语义,就必须实现equals() 和hashCode()。
3. 持久化对象的三种状态:
一个持久化类的实例可能处于三种不同状态中的某一种。
3.1. 瞬时(transient)状态:
该实例是刚用new语句创建的,还没有被持久化,不处于任何Session的缓存中。它没有持久化标识(相当于主键值)。处于瞬时状态的实例被称为瞬时对象。它的特点是:
不和任何一个Session实例关联。在数据库中没有对应的记录。
3.2. 持久化 (persistent) 状态:
已经被持久化,加入到Session缓存中。处于持久化状态的实例被称为持久化对象。
实例目前与某个Session有关联。 它拥有持久化标识(相当于主键值),并且可能在数据库中有一个对应的行。 Hibernate保证在同一个Sesion实例的缓存中,数据库中的每条记录只对应唯一的持久化对象。 它的特点是:
持久化对象总是被一个Session实例关联。持久化对象和数据库中的相关记录对应。Session在清理缓存时,会根据持久化对象的属性变化,来同步更新数据库。
3.3. 脱管(detached) 状态:
已经被持久化过,但不再处于Session的缓存中。处于脱管状态的实例被称为脱管对象。实例曾经与某个持久化上下文发生过关联,不过那个上下文被关闭了, 或者这个实例是被序列化(serialize)到另外的进程。 它拥有持久化标识,并且在数据库中可能存在一个对应的行。 对于脱管状态的实例,Hibernate不保证任何持久化标识和Java标识的关系。它的特点是:
不再位于session的缓存中,即它不再和session关联。它拥有持久化标识。
4. Session的保存、删除、更新和查询方法:
4.1. 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。
4.2. Session的update()方法:使一个脱管对象转变为持久化对象。
方法签名:public void update(Object object) throws HibernateException; 它完成以下操作:
1) 把脱管对象重新加入到Session缓存中,使它变为持久化对象。
2) 计划执行一个update语句。值得注意的是,Session只有在清理缓存的时候才会执行update语句,并且在执行时才会把持久化对象当前的属性值组装到update语句中。
4.3. 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) 在映射文件中为<id>元素设置了unsaved-value属性,并且OID取值与unsaved-value属性值匹配。
4) 在映射文件中为<version>元素设置了unsaved-value属性,并且version属性取值与unsaved-value属性值匹配。
5) 自定义了Hibernate的Interceptor实现类,并且Interceptor的isUnsaved()方法返回Boolean.TRUE。
4.4. Session的delete()方法:
方法签名:public void delete(Object object) throws HibernateException; delete()方法用于从数据库中删除与Java对象对应的记录。如果传入的参数是持久化对象,Session就计划执行一个delete语句。如果传入的参数是游离对象,先使游离对象被Session关联,使它变为持久化对象,然后计划执行一个delete语句。值得注意的也是,Session只有在清理缓存的时候才会执行delete语句。
5. 通过主键ID取得数据对象:
5.1. Session的get()方法:
方法签名:public Object get(Class clazz, Serializable id) throws HibernateException; 根据给定的OID从数据库中加载一个持久化对象,若数据库中不存在与OID对应的记录,此方法返回null。
get()方法的执行顺序如下:
1) 首先通过id在session缓存中查找对象,如果存在此id主键值的对象,直接将其返回。如果不存在,将进行第2步。
2) 在二级缓存中查找,找到后将其返回。
3) 如果在session缓存和二级缓存中都找不到此对象,刚从数据库加载拥有此id的对象。如果数据库也不存在这个拥有此id的对象,则返回null。
5.2. Session的load()方法:
方法签名:public Object load(Class theClass, Serializable id) throws HibernateException; 根据给定的OID从数据库中加载一个持久化对象,若数据库中不存在与OID对应的记录,此方法将抛出org.hibernate.ObjectNotFoundException异常。
对于get和load的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null。
6. Query接口:
Hibernate提供Query接口,它用来执行HQL语句。
6.1. 绑定参数
6.1.1. 使用 “?” 按参数位置绑定:
通过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查询语句中参数的值。
6.1.2. 使用 “:” 后跟变量名来按命名参数绑定:
可以使用命名参数来取代使用“?”设置参数的方法,这可以不用依照特定的顺序来设定参数值,如上例可改成:
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) 在同一个查询中可以多次使用。
所以,应该优先考虑使用命名参数方式。
6.2. 使用命名查询(nameQuery):
可以将HQL语句编写在程序之外,以避免硬编码在程序之中,这样要修改HQL语句时就很方便。在xxx.hbm.xml中使用<qiuery/>标签,并在<![CDATA[ 与 ]]> 之间编写HQL,如下Student.hbm.xml:
......
<hibernate-mapping>
<class name="org.qiujy.demo.User" table="user">
<id name="id" column="id" type="java.lang.Integer">
<generator class="native"/>
</id>
<property name="name" column="name" type="java.lang.String"/>
<property name="age" column="age" type="java.lang.Integer"/>
</class>
<query name="queryUserByAgeAndName">
<![CDATA[
from User as u where u.age >:minAge and u.name like :likeName
]]>
</query>
</hibernate-mapping>
|
在代码中这样来调用:
Query query = session.getNamedQuery("queryUserByAgeAndName");
query.setInteger("minAge", 25);
query.setString("likeName", "%a%");
List list = query.list();
|
6.3. Query接口的list()方法:
Query接口的list()方法用于取得一个List类的实例,此实例中包括的可能是一个对象集合,也可能是一个对象数组集合。最常见的使用是用list()方法来取得一组符合实例对象。如上示例。
6.4. Query接口的uniqueResult()方法:
当确信使用的HQL语句查询时返回的集合中只有一个对象时,就可以使用这个方法。但如果返回结果中有多个对象,使用这个方法会抛出org.hibernate.NonUniqueResultException 异常,说“query did not return a unique result”。
分享到:
相关推荐
**标题:Hibernate 操纵持久化对象** 在Java开发中,Hibernate是一个强大的对象关系映射(ORM)框架,它简化了数据库与Java对象之间的交互。本篇将详细讲解如何使用Hibernate来操纵持久化对象,这对于深入理解...
12.3.2 操纵持久化对象 12.4 选择继承关系的映射方式 12.5 映射多对一多态关联 12.6 小结 12.7 思考题 第13章 Java集合类 13.1 Set(集) 13.1.1 Set的一般用法 13.1.2 HashSet类 13.1.3 TreeSet...
12.3.2 操纵持久化对象 12.4 选择继承关系的映射方式 12.5 映射多对一多态关联 12.6 小结 12.7 思考题 第13章 Java集合类 13.1 Set(集) 13.1.1 Set的一般用法 13.1.2 HashSet类 13.1.3 TreeSet...
12.3.2 操纵持久化对象 12.4 选择继承关系的映射方式 12.5 映射多对一多态关联 12.6 小结 12.7 思考题 第13章 Java集合类 13.1 Set(集) 13.1.1 Set的一般用法 13.1.2 HashSet类 13.1.3 TreeSet...
12.3.2 操纵持久化对象 12.4 选择继承关系的映射方式 12.5 映射多对一多态关联 12.6 小结 12.7 思考题 第13章 Java集合类 13.1 Set(集) 13.1.1 Set的一般用法 13.1.2 HashSet类 13.1.3 TreeSet...
7. **操纵持久化对象** - Hibernate提供了CRUD(创建、读取、更新、删除)操作的API,如`save()`, `get()`, `update()`, `delete()`等。 - 还支持事务管理和状态管理,如托管状态和游离状态的转换。 8. **检索...
**二、操纵持久化对象** 1. **Java对象在JVM中的生命周期** - **临时状态**:新建对象未被持久化,不在Session缓存中,数据库无对应记录。 - **持久化状态**:已加入Session缓存,与Session关联,数据库有对应...
本篇文章主要关注如何通过Hibernate的Session接口来操纵对象,实现数据的持久化。 首先,我们需要理解Session在Hibernate中的角色。Session是Hibernate的核心接口之一,它负责对象的持久化操作,比如保存、更新、...
##### 14.1.2 操纵持久化对象 使用表/类映射时,你可以像处理普通对象一样操纵这些持久化对象。Hibernate会负责在对象和数据库表之间进行转换。例如,保存一个`HourlyEmployee`对象: ```java Session session = ...
8.3.2 持久化对象的特征 189 8.3.3 被删除对象的特征 190 8.3.4 游离对象的特征 191 8.4 Session接口的详细用法 191 8.4.1 Session的save()和persist()方法 191 8.4.2 Session的load()和get()方法 194 8.4.3 ...
8.3.2 持久化对象的特征 189 8.3.3 被删除对象的特征 190 8.3.4 游离对象的特征 191 8.4 Session接口的详细用法 191 8.4.1 Session的save()和persist()方法 191 8.4.2 Session的load()和get()方法 194 8.4.3 ...
"操纵持久化对象.ppt"可能涉及如何通过ORM框架,如Hibernate,来创建、读取、更新和删除(CRUD)数据库中的对象。这包括实体类的设计,配置映射文件,以及使用SessionFactory和Session对象进行数据库操作。 5. **...
hibernate入门;java对象持久化;对象-关系映射基础;映射对象标识符;映射一对多关联关系;映射一对一关联关系;...操纵持久化对象;映射组成关系;hibernate映射类型;hibernate的检索策略等等。
操纵持久化对象 698 选择继承关系的映射方式 699 映射多对一多态关联 702 内容总结 705 独立实践 705 第三十六章:HQL介绍 706 学习目标 706 HQL的出现 707 进入HQL世界 707 聚合 708 分组 709 在Java中使用HQL 709 ...
Hibernate3对象关系映射、操纵持久化对象、Hibernate相关映射、Hibernate检索策略、Hibernate检索方式、Hibernate高级配置、Java语言的反射机制、iBATIS原理及使用;Spring2概述、bean和BeanFactory等。 通过上述...
在Java编程中,持久化是将对象的状态保存到持久存储介质(如数据库)中的过程,确保即使程序关闭或系统出现故障,数据也能在后续的运行时恢复。Hibernate作为一款流行的Java对象关系映射(ORM)框架,它简化了Java...
- **操纵持久化对象** - CRUD 操作。 - 查询对象的方法。 - 更新和删除对象。 - **事务控制** - Hibernate 事务管理机制。 - 事务的隔离级别。 - 如何确保数据一致性。 - **高级映射** - 继承映射。 - ...
Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。