Hibernate里有三种对象状态:临时状态 (Transient)、持久状态(Persistent)、游离状态(Detached)
状态表格
表格中是否在缓存指Session缓存或者JPA的Persistence Context
状态 | 对象 | 是否在缓存 | 是否在数据库 | 当前对象与数据库是否有对应关系 | 备注 |
---|---|---|---|---|---|
临时状态 (Transient) | 临时对象 | 否 | 否 | 否 | new一个对象,或者从另外两个状态转换来 |
持久状态(Persistent) | 持久对象 | 是 | 是 | 是 | 进行了增加,更新操作,或者加载自数据库 |
游离状态(Detached) | 游离对象 | 否 | 否 | 曾经有,现在无 | 从session缓存中移除,但是不移除数据库记录 |
一级缓存
也称为session缓存,它和session生命周期相同,周期比较短,属于事务隔离级别。
- Session内置不能被卸载
- Session的缓存是事务范围的缓存
- Session对象的生命周期通常对应一个数据库事务或者一个应用事务
实现原理:
hibernate的缓存是通过集合实现的,hibernate中封装了list和map的集合。hibernate向一级缓存中存放数据时,同时保存快照数据,当执行flush()时,会对比一级缓存中的数据和快照中的数据是否一致,如果不一致,则执行更新。
用处:
当要查询的数据在缓存中已经存在时,hibernate将不会再向数据库发送查询语句,而是直接从缓存中获取对象。
session方法
flush()
evict()
load()
save()
saveOrUpdate()
update()
merge()
persist()
delete()
refresh()
get()
PS:
session.get()、load(支持一级缓存。createQuery()不支持一级缓存,即即使是两次相同的查询,获得list也是相同的,也会向数据库发起2次查询
Session方法概要解说:
flush()
将缓存同步到数据库,首先会将缓存数据和快照区数据进行对比,如果相同,就不会发送update()语句,如果不同,则执行update()语句,所以不一定会很发生update()语句到数据库。
session.beginTransaction();
// 通过ID从数据库中获取值,此时会产生快照
Book book1 = (Book) session.get(Book.class, 1);
// 修改属性值
book1.setName("xxx");
// 手动flush,刷新缓存到数据库,此时只是生成SQL语句,但是数据库中并没有发生变化,只有commit后,数据库才会发生相应的变化。
session.flush();
// 手动提交事务
session.getTransaction().commit();
// 关闭session的资源
session.close();
refresh()
将数据库中的数据同步到缓存中,这个过程一定会产生更新语句(是查询语句吧?),同步一级缓存和快照
session.beginTransaction();
// 从数据库中查询book,并放置到Session缓存中一份
Book book1 = (Book) session.get(Book.class, 1);
//修改缓存对象的值
book1.setName("xxx");
//又进行了一次查询操作,此时把快照中的数据与数据库一致
session.refresh(book1);
System.out.println(book1);
// 4.提交食物
session.getTransaction().commit();
// 5.关闭session资源
session.close();
clear()
清除所有对象的一级缓存,对对象的所有操作,全部失效,回复到当初和快照一样
// 启动事务操作
session.beginTransaction();
// session.setFlushMode(FlushMode.MANUAL);
// 通过ID从数据库中获取值,此时会产生快照
Book book1 = (Book) session.get(Book.class, 1);
// 修改属性值
book1.setName("xxx");
//清除一级缓存操作,此时当作事务提交的时候,数据库中并没有发生任何的变化
session.clear();
// 手动提交事务
session.getTransaction().commit();
// 关闭session的资源
session.close();
evict()
对指定的对象清除一级缓存
session.beginTransaction();
//当执行一次操作后,会把对象放置到Session缓存中
Book book1 = (Book) session.get(Book.class, 1);
Book book2 = (Book) session.get(Book.class, 2);
// 从缓存中清除book2对象所做的修改
session.evict(book2);
// 当再次执行操作时,book2还会发出SQL语句操作
Book book11 = (Book) session.get(Book.class, 1);
Book book22 = (Book) session.get(Book.class, 2);
// 手动提交事务
session.getTransaction().commit();
// 关闭资源
session.close();
session缓存中entity生命周期图
一、Hibernate中Session方法
get()/load()/Query.list()/Query.uniqueResult()/Query.iterator()/Query.scoll() 从数据库载出来的对象,即是持久对象,对应状态为持久状态
JPA中的EntityManager
在我们介绍EntityManager API之前,我们先来看看Persistence Context的概念。一个Persistence Context就是针对一个事物中一段时间内一群被管理的Entity的集合。多个具有相同唯一标识的Entity实例不能存在于同一个Persistence Context中。例如,一个Book实例的ID是12,此时就不能有第二个ID也是12的Book实例存在于相同的Persistence Context中了。只有存在于Persistence Context中的Enitity才会被EntityManager所管理,它们的状态才会反映到数据库中。Persistence Context可以被看成一个一级缓存,它可以被EntityManager当作存放Entity的缓存空间。默认情况下,Entity在Persistence Context存活,直到用户的事物结束。
事务范围内的缓存Persistence Context
EntityManager中entity生命周期
在JPA中,所有的Entity都是通过javax.persistence.EntityManager的API来管理和操纵的。当EntityManager管理Entity时,所有的Entity都会有一个唯一标识(这个标识通常是主键列),Entity的状态将会和数据库同步。当Entity脱离EntityManager的管理时,Entity就变成了一个普通的Java对象实例,这时它的状态是detached。
当我们用new关键字创建一个新Entity时,这个Entity对象存在于内存中,JPA对它没有任何了解。只有当EntityManager开始管理它时,它的状态才会和数据库同步。当调用了EntityManager.remove方法后,它就会从数据库中删除掉,但Java对象还会在内存中存在,直到被垃圾回收掉
EntityManager的方法
persist()
merge()
remove()
find()
flush()
refresh()
detach()
getReference()
session方法与Entitymanager方法对比
二者的联系
SessionFactory 对应 EntityManagerFactory;
Session 对应 EntityManager;
SessionFactory是线程安全的,Session不是线程安全的;
EntityManager 是线程安全的;
引用文章:
https://www.cnblogs.com/yuwenhui/p/7494076.html
https://blog.csdn.net/tantexian/article/details/50523270
https://blog.csdn.net/54powerman/article/details/61196215