在学习Hibernate的过程中,对象持久化时的三种状态以它们直接的转换是我们必须深入学习的,对它的深入理
解,才能更好的理解hibernate的运行机理。可以帮助我们更好的理解hibernate,JVM和sql的关系。
下面我们通过两张图了解一下这三种状态:
一:三个对象的学习:
下面这张图我主要整理了三种对象的定义和特点,作为简单的了解。
注:Hibernate三种状态中游离对象和临时对象异同:
1.两者都不会被Session关联,对象属性和数据库可能不一致;
2.游离对象由持久化对象关闭Session而转化而来,在内存中还有对象所以此时就变成游离状态了;
二:三种状态转换的状态图:
注:三种状态转化的方法都是通过session来调用。
1.瞬态到持久态的方法有save()、saveOrUpdate()、get()、load();
2.持久态到瞬态的方法有delete();
3.游离态到持久态的方法有update()、saveOrUpdate()、lock();
4.持久态到游离态的方法有:session.close()、session.evict()、session.clear()。
三:结合save(),update(),saveOrUpdate() 方法说明对象的状态
1.Save() 方法将瞬时对象保存到数据库,对象的临时状态将变为持久化状态。当对象在持久化状态时,它一直
位于 Session 的缓存中,对它的任何操作在事务提交时都将同步到数据库,因此,对一个已经持久的对象调用
save() 或 update() 方法是没有意义的。
2.update() 方法两种用途重新关联脱管对象为持久化状态对象,显示调用 update() 以更新对象。调用
update() 只为了关联一个脱管对象到持久状态,当对象已经是持久状态时,调用 update() 就没有多大意义了。
如:如果希望只有脱管对象改变了, Hibernate 才生成 update 语句,可以把映射文件中 <class> 标签的 select-
before-update 设为true, 这种会先发送一条 select 语句取得数据库中的值,判断值是否相同,如果相同就不执
行 update 语句。不过这种做法有一定的缺点,每次 update 语句之前总是要发送一条多余的 select 语句,影响性
能。对于偶尔更改的类,设置才是有效的,对于经常要更改的类这样做是影响效率的。
3.saveOrUpdate() 方法兼具 save() 和 update() 方法的功能,对于传入的对象, saveOrUpdate() 首先判断
其是脱管对象还是临时对象,然后调用合适的方法。
代码示例:
public classSessionTest extends TestCase{
public void testSave1(){
Session session = null;
Transaction tx=null;
User user=null;
try{
session=HibernateUtils.getSession();
tx = session.begionTransaction();
// Transient状态
user =new User();
user.setName=("张三");
user.setPassword("123");
user.setCreateTime(new Date());
user.setExpireTime(new Date());
//persistent状态(持久状态)
//Persistent状态的对象,当对象的属性发送改变的时候
//hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
session.save(user);
user.setName("李四");
//可以显示的调用update方法,但是在持久状态没有什么意思
session.update(user);
tx.commit();
}catch(Exception e){
e.printStackTrace();
if (tx!=null){
tx.rollback();
}
}finally{
HibernateUtils.closeSession(session);
}
//session关闭之后为Detached状态
user.setName=("王五");
try{
session=HibernateUtils.getSession();
session.beginTranSaction();
//将detached状态的对象重新纳入Session管理
//此时将变为persistent状态的对象
//persistent状态的对象,在清理缓存是会和数据库同步
session.update(user);
session.getTransaction().commit();//清除缓存
}catch(Exceptione){
e.printSatackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public void testGet1(){
Session session = null;
try{
session=HibernateUtils.getSession();
session.beginTranSaction();
//get加载上来的对象为持久对象
//执行get会马上发出查询语句
//get方法加载数据,如果不存在反回null
User user=(User)session.get(User.calss,"序列化的ID");
System.out.println(user.getName());
//persistent状态(持久状态)
//Persistent状态的对象,当对象的属性发送改变的时候
//hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
user.setName("赵柳");
session.getTransaction().commit();//清除缓存
}catch(Exceptione){
e.printSatackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public void testLoad1(){
Session session = null;
try{
session=HibernateUtils.getSession();
session.beginTranSaction();
//不会马上发出查询语句,因为load支持延迟加载
//只有真正使用这个对象的时候,在创建,对于hibernate来说,才真正发出查询语句。
//主要是为了提高性能。
//hibernate是如何实现延迟加载的?采用代理对象实现,代理对象主要采用的是CGLIB库生成的
//而不是JDK的动态代理,因为JDK的动态代理只能对实现了接口的类生成代理,CGLIB可以对类生成代理,他采用的是继承方式
//load查询,如果对象不存在,hibernate会抛出ObjectNotFoundException异常的。
User user=(User)session.Load(User.calss,"序列化的ID");
System.out.println(user.getName());
//persistent状态(持久状态)
//Persistent状态的对象,当对象的属性发送改变的时候
//hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
user.setName("王五");
session.getTransaction().commit();//清除缓存
}catch(Exceptione){
e.printSatackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public voidtestDelete1(){
Session session = null;
try{
session=HibernateUtils.getSession();
session.beginTranSaction();
User user=(User)session.Load(User.calss,"序列化的ID");
//删除,建议采用此种方法删除:先加载在删除
session.delete(user);
session.getTransaction().commit();//清除缓存
}catch(Exceptione){
e.printSatackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public voidtestDelete2(){
Session session = null;
try{
session=HibernateUtils.getSession();
session.beginTranSaction();
//手动构造Detached对象
User user=new User();
user.setID="序列化ID";
session.delete(user);
session.getTransaction().commit();//清除缓存
}catch(Exceptione){
e.printSatackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
publicvoid testUpdate1(){
Session session = null;
try{
session=HibernateUtils.getSession();
session.beginTranSaction();
//手动构造Detached对象
User user=new User();
user.setID="序列化ID";
user.setName("周六");
session.update(user);
session.getTransaction().commit();//清除缓存
}catch(Exceptione){
e.printSatackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
//建议用这种方式
publicvoid testUpdate2(){
Session session = null;
try{
session=HibernateUtils.getSession();
session.beginTranSaction();
User user=(User)session.load(User.class,"序列化ID");
user.setName("周六");
//因为处于persistent状态,所以可以不用update,也可以显示的update
session.update(user);
session.getTransaction().commit();//清除缓存
}catch(Exceptione){
e.printSatackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
}
总结:
学习了解持久化的三个对象和三种状态直接的转换,是学习Hibenrnate的基础,对我们后面深入学习Hibenrnate提
供帮助。我们会发现所有状态的转变都是以Session为轴,对Session的操作会引起状态的改变,这其中我们要重点区分
save(),update(),saveOrUpdate()三种方法的不同,以及load()和get()方法的区别(load支持延迟加载)。