十三、hibernate对象的三种状态与懒加载机制

一、对象状态简介

1.瞬时态(transient):数据库中没有数据与之对应,超过作用域会被JVM回收,一般是new出来的且与session没有关联的对象

2.持久态(persistent):数据库中有数据与之对应,当前与session有关联,并且相关联的session没有关闭,事务没有提交.(持久态对象状态发生改变,在事务提交时会影响到数据库)

3.脱管态/游离态(detached):数据库中有数据与之对应,但当前没有session与之关联,脱管对象状态发生改变,hibernate不能检测到。

 

Course c1=new Course();//瞬时态

c1.setCname("PHP");//瞬时态

c1.setCcredit(3);//瞬时态

c1.setCid(19);//瞬时态

 

Session session=HibernateUtil.getCurrentSession();

Transaction ts=null;

try {

session=HibernateUtil.getCurrentSession();

ts=session.beginTransaction();

 

session.save(c1);//持久态,此时c1处于session管理之下

c1.setCname("python");//持久态的对象状态发生改变,hibernate会检测到,并且会同步到数据库中

ts.commit();

 

c1.setCcredit(5);//ts已经提交,此时处于游离态,状态改变hibernate检测不到,也不会同步到数据库中

} catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

if(ts!=null) ts.rollback();

}finally{

if(session!=null&&session.isOpen()){//事务提交或者关闭session都会使对象处于游离态

session.close();

}

}

 

二、hibernate对象状态图

 

 

 

三、懒加载机制

 

默认情况下,xxx.hbm.xml<class lazy=”true”>,即启用了懒加载机制。

 

以下情况应注意懒加载机制:

 

load方法

Load先到缓存(session缓存/二级缓存)中去查,如果没有则返回一个代理对象(不马上到DB中去找,即不发出sql语句),等后面使用这个代理对象操作的时候,才到DB中查询(发出SQL语句),这就是我们常说的load在默认情况下支持延迟加载(lazy),如果禁用了懒加载机制,则命令Load先到缓存(session缓存/二级缓存)中去查,如果没有则立即发出SQL语句到数据库中查询。

session外得到对象属性

Employee e=(Employee) session.get(Employee.class, 1);

System.out.println(e.getName()+e.getDept().getName());

 

以上代码在session中执行并不会出错,但是如果我是将e返回给上一级,在别的地方处理e,例如在session外打印e.getDept().getName(),则会报错could not initialize proxy - no Session不能初始化代理对象,没有session。其实在sessione.getName()不会报错,因为这是它本身的属性,而e.getDept().getName()需要session再发出sql语句去查,所以在session已经关闭的情况下就报错了。

 

这个异常有两种处理方式,

一是Department.hbm.xml<class lazy=”false”>,关闭懒加载。

二是在得到e之后就强制session去发出sql得到e.getDept(),并绑定在e身上,此时e.getDept()也相当于是e的自身的属性了。

具体代码:

e=(Employee) session.get(Employee.class, 1);

Hibernate.initialize(e.getDept());//发出sql语句得到dept所有属性

 

原文地址:https://www.cnblogs.com/myz666/p/8425129.html