理解持久化类状态、生命周期和Session接口方法工作原理

持久化实例有三种状态:
1.临时状态(transient):刚用new语句创建,还没有被持久化,不处于Session的缓存中。处于临时状态的Java对象称为临时对象。
2.持久化状态(persistent):已经被持久化,加入到Session的缓存中。处于持久化状态的Java对象称为持久化对象。
3.游离状态(detached):已经被持久化,但不再处于Session的缓存中。处于游离状态的Java对象称为游离对象。

持久化实例的生命周期:
new出一个对象表示生命周期开始。
只要有变量引用该实例或者处于Session的缓存当中,就一直处于生命周期中。
直到没有任何变量引用该实例并且不在Session的缓存当中,生命周期结束。

在默认情况下,Session会在下面的时间点清理缓存。
1 当应用程序调用net.sf.hibernate.Transacation的commit()方法的时候,commit()方法先清理缓存,然后再向数据库提交事务。
2 当应用程序调用Session的find()或者iterate()时,如果缓存中持久化对象的属性发生了变化,就会先清理缓存,以保证查询结果能反映持久

化对象的最新状态。
3 当应用程序显示调用Session的flush()方法的时候。
Session进行清理缓存的例外情况是:如果对象使用native生成器来生成OID,那么当调用Session的save()保存该对象时,会立即执行向数据库插

入该实体的insert语句。
注意Session的commit()和flush()方法的区别。flush()方法进行清理缓存的操作,执行一系列的SQL语句,但不会提交事务;commit()方法会先

调用flush()方法,然后提交事务。提交事务意味着对数据库所做的更新被永久保存下来。

Session在清理缓存时,按照以下顺序执行SQL语句:
1.按照应用程序调用session.save()方法的衔后顺序,执行所有对实进行插入的insert语句。
2.执行所有对实体进行更新的update语句。
3.执行所有对集合进行删除的delete语句。
4.执行所有对集合元素进行删除、更新或者插入的SQL语句。
5.执行所有对集合进行插入的insert语句。
6.按照应用程序调用session.delete()方法的先后顺序,执行所有对实体进行删除的delete语句。


下面用代码来理解以上概述,同时理解Session接口的save()、update()、saveOrUpdate()、delete()、load()和get()方法的工作原理。
Session的save()方法
public static void main(String[] args) {
Session session = HibernateUtil.getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Customer customer = new Customer(); //customer对象处于临时状态
customer.setName("David");
session.save(customer); //customer对象处于持久化状态
tx.commit();
customer.setName("Bruce"); //无效
session.close(); //customer对象处于游离状态
} catch(Exception e) {
if (tx != null) {
tx.rollback();
}
e.printStackTrace();
}
}
/**Output:
Hibernate: insert into CUSTOMERS (NAME) values (?)
*/
session.save()的行为:
1.将持久化实例加入到缓存中,使它变为持久化对象。
2.为持久化对象分配唯一的OID。
3.组装insert语句,但不立即执行,Session清理缓存时才执行。

customer.setName("Bruce");并没有执行,因为这条语句之后没有清理缓存,而是直接关闭Session。
如果想要执行该update操作,以下两种方式都可以
session.save(customer);
customer.setName("Bruce");
tx.commit(); //因为commit()操作会清理缓存
或者
session.save(customer);
tx.commit();
customer.setName("Bruce");
session.flush();
/**Output:
Hibernate: insert into CUSTOMERS (NAME) values (?)
Hibernate: update CUSTOMERS set NAME=? where ID=?
*/

如果在修改了对象属性后再保存一次,不会理会那个语句,也不会重复执行SQL
Customer customer = new Customer();
customer.setName("David");
session.save(customer);
customer.setName("Phil");
session.save(customer); //多余的语句
tx.commit();
/**Output:
Hibernate: insert into CUSTOMERS (NAME) values (?)
Hibernate: update CUSTOMERS set NAME=? where ID=?
*/

如果多次修改name属性,只会执行一条Update语句。
Customer customer = new Customer();
customer.setName("David");
session.save(customer);
customer.setName("Phil");
customer.setName("AA");
customer.setName("BB");
tx.commit();
/**Output:
Hibernate: insert into CUSTOMERS (NAME) values (?)
Hibernate: update CUSTOMERS set NAME=? where ID=?
*/
因为对象进入缓存的时候(这里是save()的时候),会为持久化对象产生一份快照,最后保存的时候会和快照对比哪些属性值改变了。

Session的update()方法
public static void main(String[] args) {
try {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Customer customer = new Customer(); //customer对象处于临时状态
customer.setName("David");
session.save(customer); //customer对象处于持久化状态
session.update(customer); //不执行update语句,因为属性没有改变
tx.commit();
session.close(); //customer对象处于游离状态

Session session2 = HibernateUtil.getSession();
tx = session2.beginTransaction();
customer.setName("Phil"); //customer对象处于游离状态
session2.update(customer); //customer对象处于持久化状态
customer.setName("Bruce");
tx.commit();
session2.close(); //customer对象处于游离状态
} catch(Exception e) {
e.printStackTrace();
}
}
/**Output:
Hibernate: insert into CUSTOMERS (NAME) values (?)
Hibernate: update CUSTOMERS set NAME=? where ID=?
*/

session.update()的行为:
1.将游离对象重新加入到Session的缓存中,使它变为持久化类。
2.update()方法不会组装update语句,当清理缓存时才组装update语句。

因此上面的代码只执行了了一条update语句,即使执行多次update()方法,也只会执行一次update语句
//customer是游离对象
Session session2 = HibernateUtil.getSession();
tx = session2.beginTransaction();
customer.setName("Phil");
session2.update(customer);
customer.setName("Bruce");
session2.update(customer);
session2.update(customer);
tx.commit();
session2.close();
/**Output:
Hibernate: update CUSTOMERS set NAME=? where ID=?
*/

即使没有修改任何对象属性,update()操作都会执行一条update语句。
//customer是游离对象
Session session2 = HibernateUtil.getSession();
tx = session2.beginTransaction();
session2.update(customer);
tx.commit();
session2.close();
/**Output:
Hibernate: update CUSTOMERS set NAME=? where ID=?
*/
因为session2没有customer的快照,所以无法判断属性是否有改变。

Session的saveOrUpdate()方法
同时包含save()和update()方法的功能。如果传入的参数是临时对象,就执行save()方法;如果传入的参数是游离对象,就执行update()方法;

如果传入的参数是持久化对象,那就直接返回;

Session的load()和get()方法
这两个方法都是从数据库加载一个持久化对象。
区别在于:
1.加载的OID在数据库中没有对应的记录时,load()方法会抛org.hibernate.ObjectNotFoundException异常;get()方法返回null;
2.load()方法是延迟加载,get()方法是立即加载。

Session的delete()方法
从数据库中删除与Java对象对应的记录。如果传入的参数是持久化对象,Session就计划一个delete语句;如果传入的参数是游离对象,先使游离

对象被Session关联,使它变为持久化对象,然后计划执行一个delete语句;如果传入的参数是临时对象,直接返回,不抛错。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值