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,禁用一级缓存的主要内容,如果未能解决你的问题,请参考以下文章