Hong's Blog
Be Agile. Be Smart. Be Visionary. Be Dedicated.
Persistence context和EntityManager实际上是同一个东西。Persistence context更多地 是表示一种概念(concept)或者一个名词(term);EntityManager就是Persistence context 在java代码里相应的类。
Persistence context
EntityManager
Persistence context/EntityManager管理着一个entity的集合。EntityManager提供了管理 entity的接口:
Persistence context/EntityManager
persist() //把entity放到pc里管理 merge() //把传进来的entity拷贝一份,把拷贝放到pc里管理 detach() //把entity从pc中移出来,pc不再管理这个entity remove() //删除entity,交易提交时,数据库相应的列也会删除 flush() //把pc里的entity同步到数据库里 find() createQuery() ...
new出来的entity不会直接放到EntityManager里,需要调一下persist()或者merge()。 只有被EntityManager管理的entity在transaction提交时才会写到数据库里。
persist()
merge()
一般一个transaction有一个persistence context;但是,persistence context也可以配置成 跨多个transaction的。
Persistence context就是一个缓存,叫first level cache(L1 cache)。数据库的一行(row)在一个 persistence context只有一个对应的entity。对一个entity的CRUD都是先作用在first level cache 上,等transaction提交时再写到数据库里。First level cache可以减少对数据库的操作。比如查找某 个行时,先看first level cache里是不是已经有对应的entity存在了;如果存在就不用再查询数据库了。 同样,对entity的(多次)更新等操作也是先写到这个缓存里,最后再(一次)提交到数据库里。
因为可能有多个persistence context(比如一个transaction有一个persistence context),数据 库的同一行可能在多个persistence context里都有对应的entity。这时候,就要通过加锁策略(locking) 来保证数据的一致性(乐观锁/悲观锁)。
可以看到first level cache的生命周期是和一个persistence context/transaction绑定的;而且 不同的first level cache之间是互相隔离的。Second level cache(L2 cache)则是一个application 级别的缓存;不同的persistence context共享同一个second level cache。查找一个entity时, 会先看L1 cache;找不到再看L2 cache;最后才真正去数据库里找。
不同的JPA实现有不同的L2 cache实现。有些JPA实现(比如EclipseLink)会默认打开L2 cache,另外一些 可能默认是关闭的。
L2 cache的好处是减少数据库操作,可以读得更快。
L2 cache的缺点是:
对于那些经常运行的,且参数和涉及到的表都没有变化的query,query cache会有助提高性能。
JPA 2.0提供了一些L2 cache相关的API。比如,javax.persistence.Cache接口,包含了contains(), evict()等方法;@Cacheable可以标注一个entity是不是要被缓存。另外,persistence.xml提供了 <shared-cache-mode>标签,可以指定缓存的策略;它可以是下列值:
javax.persistence.Cache
contains()
evict()
@Cacheable
<shared-cache-mode>
除了在persistence.xml静态地配置,也可以通过设置entity manager factory来动态地配置。
另外,一些JPA实现还提供了自己的(更丰富的)API来配置L2 cache。比如EclipseLink和Hibernate都提供 了@Cache(EclipseLink的文档还推荐使用@Cache来替代标准的@Cacheable)。
这篇文章推荐为以读为主、不常修改、不关心是否stale的entity打开L2 cache。(对于那些经常 写的entity,即使你没打开L2 cache,它还是会发生并发冲突的问题,只是冲突发生在数据库级别而已; 所以前一句的话真正论据是什么?) 对于并发写冲突问题,文章还提到了
“configure expiration, refresh policy to minimize lock failures” (why & how?)
如果你觉得这篇文章对你有用,可以微信扫一扫表示🙏 / If you find this post is useful to you, buy me 🍶 via Wechat
JPA里的Second Level Cache
基本概念
Persistence context
和EntityManager
实际上是同一个东西。Persistence context
更多地 是表示一种概念(concept)或者一个名词(term);EntityManager
就是Persistence context
在java代码里相应的类。Persistence context/EntityManager
管理着一个entity的集合。EntityManager
提供了管理 entity的接口:new出来的entity不会直接放到EntityManager里,需要调一下
persist()
或者merge()
。只有被EntityManager管理的entity在transaction提交时才会写到数据库里。
一般一个transaction有一个persistence context;但是,persistence context也可以配置成 跨多个transaction的。
不同的缓存
First Level Cache
Persistence context就是一个缓存,叫first level cache(L1 cache)。数据库的一行(row)在一个 persistence context只有一个对应的entity。对一个entity的CRUD都是先作用在first level cache 上,等transaction提交时再写到数据库里。First level cache可以减少对数据库的操作。比如查找某 个行时,先看first level cache里是不是已经有对应的entity存在了;如果存在就不用再查询数据库了。 同样,对entity的(多次)更新等操作也是先写到这个缓存里,最后再(一次)提交到数据库里。
因为可能有多个persistence context(比如一个transaction有一个persistence context),数据 库的同一行可能在多个persistence context里都有对应的entity。这时候,就要通过加锁策略(locking) 来保证数据的一致性(乐观锁/悲观锁)。
Second Level Cache
可以看到first level cache的生命周期是和一个persistence context/transaction绑定的;而且 不同的first level cache之间是互相隔离的。Second level cache(L2 cache)则是一个application 级别的缓存;不同的persistence context共享同一个second level cache。查找一个entity时, 会先看L1 cache;找不到再看L2 cache;最后才真正去数据库里找。
不同的JPA实现有不同的L2 cache实现。有些JPA实现(比如EclipseLink)会默认打开L2 cache,另外一些 可能默认是关闭的。
L2 cache的好处是减少数据库操作,可以读得更快。
L2 cache的缺点是:
Query Cache
对于那些经常运行的,且参数和涉及到的表都没有变化的query,query cache会有助提高性能。
L2 Cache的配置
JPA 2.0提供了一些L2 cache相关的API。比如,
javax.persistence.Cache
接口,包含了contains()
,evict()
等方法;@Cacheable
可以标注一个entity是不是要被缓存。另外,persistence.xml提供了<shared-cache-mode>
标签,可以指定缓存的策略;它可以是下列值:除了在persistence.xml静态地配置,也可以通过设置entity manager factory来动态地配置。
另外,一些JPA实现还提供了自己的(更丰富的)API来配置L2 cache。比如EclipseLink和Hibernate都提供 了@Cache(EclipseLink的文档还推荐使用@Cache来替代标准的@Cacheable)。
这篇文章推荐为以读为主、不常修改、不关心是否stale的entity打开L2 cache。(对于那些经常 写的entity,即使你没打开L2 cache,它还是会发生并发冲突的问题,只是冲突发生在数据库级别而已; 所以前一句的话真正论据是什么?)
对于并发写冲突问题,文章还提到了
如果你觉得这篇文章对你有用,可以微信扫一扫表示🙏 / If you find this post is useful to you, buy me 🍶 via Wechat