
Guice Account Scope
场景H2
存在实体A、B,A包含一个和B的一对多关系,即
java
A {@OneToManyList<B>}
现在需要假设需要更新A中的某个普通属性,更新完后返回一个包含关联关系B的A对象。
需要注意的是,这里业务场景对A的更新,不是通过设置一个托管状态的A的set方法实现的,而是merge一个页面提交上来的A,因此这个A本身是不包含的关联关系的值的。
现象H2
调用entityManager.merge 返回的A的关联关系B的值是空的,通过懒加载获取B无法触发。
重新查询无法正常获取到关联属性,框架会返回一级缓存中的更新时对象(没有关联属性)
原因H2
下面的原因只是推测,没有得到证实
merge的时候数据库中的代理对象不会被设置到merge的结果
如果是关联关系的owner则需要更新成当前的关联值
如果不是关联关系的owner那设置了也无妨
所以结论上讲,关联关系的值以是以merge的当前对象为主的。
再次查询关联没有被更新
以当前一级缓存的状态为主,如果关联关系只是之前没fetch,新的查询出来的关联关系是有fetch的值的,那fetch的值会被更新上去。
但如果一级缓存中的关联关系都是空的,那么即便新的查询出来的关联关系是有fetch的值也不会被更新上去。
WorkaroundH2
merge完后由于没有关联属性值,后续的查询也无法把关联值设置进去,这个问题可以进行一次refresh。但需要注意的是merge完后需要手动flush,否则更新状态会被fresh覆盖
- merge
- flush
- refresh
- fetch query
其他一级缓存相关的问题H2
如果查询过一次A并且把B fetch出来了,然后直接删除B,再次查询A,返回的A依然会包含刚才删除的B,因为一级缓存中的A包含了删除之前的B。
如果一开没有fetch B,那么再次触发的查询,能够查询到正确的删除后的结果。但是这里依然是有个注意点,删除B后,一定要手动flush,因为如果使用find 查询是不会自动flush的(如果第二次的A查询使用JPQL则没有问题)。
By default, Hibernate uses the AUTO flush mode which triggers a flush in the following circumstances:
- prior to committing a
Transaction - prior to executing a JPQL/HQL query that overlaps with the queued entity actions
- before executing any native SQL query that has no registered synchronization
find 和JPQL对一级缓存的处理有有些不同:
find如果一些缓存里有缓存,则直接不查询- JPQL 无论如果都会去查询,然后和一级缓存中的数据进行合并。
评论
新的评论
上一篇
支持CommonJS 和 ES6模块
一个模块同时要支持 CommonJS 和 ES6 两种格式,也很容易。 如果原始模块是 ES6 格式,那么需要给出一个整体输出接口,比如 export default obj ,使得 CommonJS 可以用 import() 进行加载。 如果原始模块是 CommonJS 格式…
下一篇
CORS
CORS包含两部分验证 服务器端验证 浏览器验证 withCredential CORS请求当需要携带Cookie等敏感信息时,需要设置 XMLHttpRequest.withCredential 参数,etch、axios 等请求库也可以设置该参数。但是设置设置改参数后,…
