那些年你不了解的hibernate!今天我带你飞

6 年前

相信好多人工作了几年,还是对hibernate三种状态一知半解,特别对 session级别的save,update等方法 到底执行几次SQL语句摸不透?

相信你看完的话,对hibernate有更深刻的理解,对hibernate开发,对原理,会有更深的了解,信不信?那你认真看完

概念性的东西我就不多说,对于初学者来说很好理解。

下面利用 hibernate的三种状态 让你理解session的工作原理。


1、transient(瞬时状态)

其实就是new一个对象后,还没有保存到数据库中,未持久化


--session begin--
Car car = new Car();
car.setName("car1");
car.setColor("blue");
//car处于Transient(瞬时状态),在session缓存中不存在car对象
session.save(car);
//执行save后,session缓存中和数据库中存在car对象,状态转换为【持久状态】     
--session commit--

执行完毕save以后,这个比较好理解,对象就变为持久化,会发出一条sql语句:

Hibernate: insert into t_car (id, name, color) values (?, ?, ?)

2、persistent(持久状态)

其实持久化状态就是已经被保存到数据库中,session中也存在该对象

2.1)持久化后执行update动作

--session begin--
Car car = new Car();
car.setName("car1");
car.setColor("blue");
//car处于Transient(瞬时状态),在session缓存中不存在car对象
session.save(car);
//执行save后,session缓存中和数据库中存在car对象,状态转换为持久状态        
car.setColor("red"); 
//这个car对象会与session缓存中car对象进行比较,如果不同,就发出update语句
--session commit--

当car持久化后,又重新修改了属性color值,在事务commit提交时, hibernate比较当前对象和session缓存中的car对象是否相同 ,如果相同,则不会发送update语句,否则,会发出update语句。

Hibernate: insert into t_car ((id, name, color) values (?, ?, ?)
Hibernate: update t_car set color=? where id=?

2.2)持久化后多次调用 session.update

--session begin--
Car car = new Car();
car.setName("car1");
car.setColor("blue");
//car处于Transient(瞬时状态),在session缓存中不存在car对象
session.save(car);
//执行save后,session缓存中和数据库中存在car对象,状态转换为持久状态          car.setColor("red");   
session.update(car);   
car.setColor("black");
session.update(car);        
//这个car对象会与session缓存中car对象进行比较,如果不同,就发出update语句 
--session commit--

!!重点就是这里!!:

为什么session执行update或者save了多次, 只提交一次update语句
注意session级别里面的缓存, 只有在commit的时候才会去比较 对象是否不同,不同才会发出
sql语句执行。
Hibernate: insert into t_car ((id, name, color) values (?, ?, ?)
Hibernate: update t_car set color=? where id=?

2.3)持久化后session.clear


大家看完上面的说明以后,hibernate最重要的是 session级别缓存 ,多次update持久化对象只会执行一次语句。但是clear以后会怎样?

顾名思义:清除session中的缓存 ,既然session里面缓存不存在那个对象了,你猜会怎样?

Car car = session.get(Car.class,1);	
Car car2 = session.get(Car.class,1);	
Car car3 = session.get(Car.class,1);
//上面不管获取几次id=1的car对象只会发一条sql语句,因为去session缓存里面获取	
session.clear();
//但是session缓存被清空了,下面还会发一次sql查询语句	
Car car4 = session.get(Car.class,1);

如果已经get一次对象保存到session缓存中,你如果重复发送多少条get对象Car语句,hibernate都是 先去缓存里获取 ,也就是 只发一条sql语句 去查询,但是一旦 session被clear ,然后缓存中没有了,会 重新再发sql 去获取。

Hibernate: select car0_.id as id0_0_, car0_.name as name0_0_, car0_.color as color0_0_ from t_car car0_ where car0_.id=?
Hibernate: select car0_.id as id0_0_, car0_.name as name0_0_, car0_.color as color0_0_ from t_car car0_ where car0_.id=?

2.4)持久化后session.flush()

想必大家知道session的强大作用了,当执行flush的时候会发现什么?

顾名思义:强制缓存的内容与数据库内容做同步,类似于提交

Car car = session.get(Car.class,1);
a.setColor("aa");
a.setColor("bb");
//明显只会发送一条sql的update语句	
--session commit--

如上因为hibernate只会在事务commit提交时,去比较缓存对象是否不同,发送一条语句更新

Hibernate: update t_car set color=? where id=?

如果加了flush会怎样?

Car car = session.get(Car.class,1);
a.setColor("aa");
//发送一条sql的update语句
sessoin.flush();//此时session强制合数据库同步为aa,所以需要先发送同步"aa"语句
//因为缓存已经和数据库进行同步了,还会再发送一条sql的update语句进行同步"bb"
a.setColor("bb");	
--session commit--