2010-05-18 4 views
3

Supposons que je donne les résultats suivants mappage de classe de domaine à une table d'héritage, en utilisant lecture seule cache de second niveau, et ayant un champ transitoire:Grails/GORM, Désactiver premier niveau Cache

class DomainObject { 
static def transients = ['userId'] 

Long id 
Long userId 

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

J'ai problème, les références à DomainObject sont partagées en raison de la mise en cache de premier niveau, et donc les champs transitoires s'écrivent les uns sur les autres. Par exemple,

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

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

assert r1.userId == 34 

Autrement dit, r1 et r2 sont des références à la même instance. Ce n'est pas souhaitable, je voudrais mettre en cache les données de la table sans partager de références. Des idées?

[Modifier]

Comprendre la situation mieux maintenant, je pense que ma question se résume à ce qui suit: Y at-il de toute façon à désactiver la première cache de niveau pour une classe de domaine spécifique tout en utilisant cache de second niveau?

[Modifier]

Comme il semble y avoir aucun moyen propre pour atteindre cet objectif, nous avons plutôt opté pour redessiner autour de la nécessité.

Répondre

2

Veuillez ignorer ma réponse précédente, je n'ai pas entièrement compris votre problème.

Cependant, ce qui suit fonctionnera (code testé):

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 
+0

Merci. Bien que cela fonctionne pour mon exemple simple, ce n'est pas une approche pratique à prendre tout au long de l'application. Je suis surpris: p.266 et p.276 dans Definitive Guide To Grails reconnaissent la réutilisation d'instance comme faisant partie du cache de premier niveau mais ne considèrent pas le scénario que j'ai présenté. Je me demande s'il existe un moyen de désactiver le cache de premier niveau pour un objet de domaine spécifique, c'est peut-être le problème et le cache de second niveau fonctionnera comme je le souhaite. –

+0

Je ne vous connais pas toutes les exigences donc je ne peux pas vraiment aider sauf de ma réponse pour ce petit exemple. Cela dit, même l'exemple me semble étrange ... – fabien7474

+0

L'idée ici peut être comparée à un multi-ensemble qui est augmenté (via des champs transitoires) et transformé en un ensemble normal: par ex. [pomme, pomme, orange, orange] -> [pomme ', pomme' ', pomme' '', orange ', orange' '] –

0

J'imagine que vous pourriez, dans BootStrap, métaclasse sur une nouvelle méthode get() (ou une méthode par un autre nom) qui pourrait faire le même - appelez l'original get() et jetez l'objet.

Quel est votre scénario d'utilisation qui nécessite que les champs transitoires ne soient pas partagés? Vous pouvez toujours obtenir une nouvelle session Hibernate pour chacun des emplacements d'utilisation. La session Hibernate est ce qui maintient le cache de premier niveau.

+0

Merci John. C'est une bonne idée, mais je ne pouvais pas le faire fonctionner: def oldGet = SomeDomain. &get; SomeDomain.metaClass.'static '= {id -> def sd = ancienGet (id); sd.discard(); Dakota du Sud}; a entraîné un stackoverflow, je ne sais pas pourquoi. En ce qui concerne le scénario d'utilisation, ma capacité à le décrire diminue, puisque nous avons décidé de le reconcevoir, ce qui est probablement la meilleure chose à faire, car cela va à l'encontre de la conception de GORM. –

0

Vous pouvez utiliser DomainObject.findById (1) au lieu de DomainObject.get (1). Comme le cache de la méthode "get" est le résultat de la requête, mais pas le précédent.

+0

Hmm, je m'attendais à ce que cette bonne idée fonctionne, mais trouvé DomainObject.findById (1) .is (DomainObject.findById (1)) pour être vrai. –

Questions connexes