Grails / GORM,禁用一级缓存

Posted

技术标签:

【中文标题】Grails / GORM,禁用一级缓存【英文标题】:Grails / GORM, Disable First-level Cache 【发布时间】:2011-02-21 00:15:27 【问题描述】:

假设我有以下域类映射到旧表,利用只读二级缓存,并具有瞬态字段:

class DomainObject 
 static def transients = ['userId']

 Long id
 Long userId

 static mapping = 
  cache usage: 'read-only'
  table 'SOME_TABLE'
 

我有一个问题,对 DomainObject 的引用由于一级缓存而被共享,因此瞬态字段正在相互覆盖。例如,

def r1 = DomainObject.get(1)
r1.userId = 22

def r2 = DomainObject.get(1)
r2.userId = 34

assert r1.userId == 34

也就是说,r1 和 r2 是对同一个实例的引用。这是不可取的,我想缓存表数据而不共享引用。有什么想法吗?

[编辑]

现在更好地了解情况,我相信我的问题归结为以下几点:是否仍然在使用二级缓存的同时禁用特定域类的一级缓存?

[编辑]

由于似乎没有明确的方法来实现此目标,因此我们选择围绕它的需要重新设计。

【问题讨论】:

【参考方案1】:

请忽略我之前的回答,我没有完全理解你的问题。

但是,以下将起作用(代码测试):

def r1 = DomainObject.get(1)
r1.userId = 22
r1.discard() //BE CAREFUL WITH THIS, YOU MIGHT END UP WITH a LazyInitializationException

def r2 = DomainObject.get(1)
r2.userId = 34

assert r1.userId == 22

【讨论】:

谢谢。虽然这对于我的简单示例确实有效,但它并不是贯穿整个应用程序的实用方法。我很惊讶:Grails 权威指南中的 p.266 和 p.276 承认实例重用是一级缓存的一部分,但不考虑我提出的场景。我想知道是否有办法关闭特定域对象的一级缓存,也许这就是问题所在,二级缓存会按我想要的方式工作。 我不知道你的全部要求,所以除了我对这个小例子的回答之外,我真的无能为力。也就是说,即使是这个例子对我来说也很奇怪...... 这里的想法可以比作一个多集,它被增强(通过瞬态场)并转换成一个普通集:例如[苹果,苹果,苹果,橙子,橙子] -> [苹果',苹果'',苹果''',橙子',橙子'']【参考方案2】:

我想你可以在 BootStrap 中,在一个新的 get() 方法(或任何其他名称的方法)上执行相同的操作 - 调用原始的 get() 并丢弃该对象。

您的使用场景是什么要求不共享瞬态字段?您总是可以为每个使用位置获得一个新的 Hibernate 会话。 Hibernate 会话负责维护一级缓存。

【讨论】:

谢谢约翰。这是个好主意,但我无法让它工作: def oldGet = SomeDomain.&get; SomeDomain.metaClass.'static' = id -> def sd = oldGet(id); sd.discard(); sd;导致***,我不知道为什么。至于使用场景,我描述它的能力正在减弱,因为我们决定围绕它重新设计,这可能是最好的做法,因为它显然违背了 GORM 的设计方式。【参考方案3】:

您可以使用 DomainObject.findById(1) 代替 DomainObject.get(1)。由于“get”方法缓存了查询结果,但前者没有。

【讨论】:

嗯,我期待这个好主意能奏效,但发现 DomainObject.findById(1).is(DomainObject.findById(1)) 是真的。

以上是关于Grails / GORM,禁用一级缓存的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis-plus流程图解和使用,一级和二级缓存禁用启用详解,map的k-v入库,自增id,分页查询等各种骚操作

Mybatis缓存

一级数据缓存,一级指令缓存和二级缓存有啥区别?

什么是一级缓存,什么是二级缓存?

一级缓存和二级缓存有啥区别

谁给我解释一下一级缓存和二级缓存啊~