Question

Existe-t-il un moyen d'utiliser des objets Flyweight avec le mappage de persistance en hibernation? Mon modèle de données contient de nombreux objets qui seront identiques. Au lieu d'avoir une instance distincte pour chacun de ces mêmes objets, j'aimerais utiliser le modèle de conception Flyweight et faire référence au même objet physique. Comment y parvenir en veille prolongée?

Btw. Est-ce que toutes les machines virtuelles optimisent l'utilisation des chaînes de manière à ce que, lorsque la même chaîne est utilisée plusieurs fois, ce soit toujours la même instance physique?

Était-ce utile?

La solution

Cela dépend.

Pour les valeurs en lecture seule , vous pouvez facilement implémenter un modèle poids massique en créant un UserType personnalisé qui renverra à chaque fois des objets d'un pool et non de nouvelles instances.

Pour les entités, Hibernate est sain par défaut. Il veut être cohérent d’une transaction à l’autre et ne partagera donc pas les entités entre les sessions afin d’éviter les situations de concurrence critique de vos données - et je ne pense pas que ce soit ce que vous souhaitiez.

Mais dans le cas contraire (et cela est totalement déconseillé sans vraiment savoir ce que vous faites), vous pouvez implémenter Interceptor.getEntity (), qui est destiné à la mise en cache de second niveau. Selon cette méthode, vous pouvez renvoyer une entité (même certaines partagées par d’autres sessions) et vous obtiendrez effectivement un modèle de poids mouche pour vos entités.

MAIS je vous recommande vivement de ne pas utiliser cette méthode pour assurer la cohérence de vos données. Il est bien mieux de faire référence aux valeurs de poids massique immuables immuables référencées par des entités plutôt qu’à essayer de pondérer à la volée les entités réelles.

Autres conseils

Oui, vous pouvez implémenter le modèle Flyweight avec Hibernate.

Le modèle poids massique permet de réduire l'utilisation de la mémoire par instance . La stratégie consiste à partager autant d’états que possible entre les instances poids massique. Dans votre cas, l’état partageable est tout sauf l’identificateur d’objet hibernate et un état supplémentaire pour conserver l’identité de l’objet .

Chaque instance flyweight a besoin de sa propre identité d'objet . L’état supplémentaire est le moyen de mettre en œuvre l’identité pour distinguer les objets qui partagent un état commun.

public boolean equals(Object obj){
  Fly other; [..]//check type
  //null checks ommitted
  return other.myState.equals(myState) && other.commonState.equals(commonState); 
}

Si l'identité de l'objet est partagée entre des instances, hibernate interprètera toutes les instances physiques (références) comme la même instance. Hibernate utilise la méthode equals pour vérifier l'identité de l'objet et votre implémentation égale devrait renvoyer (! A.equals (a) == true) , ce qui est illégal. Égal doit être réfléchi. Si vous rompiez ce contrat, toutes les bibliothèques dépendantes du contrat le seront (collections, mise en veille prolongée, etc.).

Vous ne pouvez pas implémenter la méthode equal à l'aide de l'identificateur d'objet hibernate pour distinguer les objets. Cela rendrait l'identité de l'objet dépendante de l'état de persistance (persistant ou transitoire).

Une des façons de modéliser l'état commun en veille prolongée consiste à associer un à plusieurs les objets d'état partagés et les objets flyweight. (Peut-être que quelqu'un a une idée de la façon de mapper les données sans joindre deux tables?)

Chaîne: uniquement les chaînes internalisées seront partagées. Ce n'est pas la meilleure solution la plupart du temps. Il convient aux symboles (nom de classe, nom de méthode, etc.). Les chaînes internalisées ne seront jamais récupérées et vous devez avoir une instance String qui sera récupérée de toute façon new String ("..."). Intern () . Cela ne sauvera pas les allocations. Le seul avantage mineur est que la chaîne de base ne survivra pas à une génération gc ou pourrait être allouée sur la pile (avec l'analyse d'échappement dans les points chauds activée et applicable).

  

Est-ce que toutes les machines virtuelles optimisent l'utilisation des chaînes de telle sorte que, lorsque la même chaîne est utilisée plusieurs fois, ce sera toujours la même instance physique?

J'en doute beaucoup. Dans le même fichier de classe, lorsque défini comme suit:

String s1 = "Yes";
String s2 = "Yes";

vous aurez probablement s1 == s1.

Mais si vous avez comme:

String x = loadTextFromFile(); // file contains es
StringBuilder b = new StringBuilder();
s2 = b.append("Y").append(x).toString(); // s2 = "Yes"

Je ne pense pas que le moteur d'exécution vérifie et compare toutes les chaînes chargées à la valeur de retour de leur constructeur.

Donc, comparez toujours les objets avec equals (). De toute façon, c’est un bon conseil puisque tout bon égal commence par:

if (this == o) {
    return true;
}

Si vos objets implémentent l'égalité par identité, Hibernate n'aura qu'une seule instance associée à cette clé primaire. Je ne crois pas que ce soit exactement la même idée que Flyweight, mais le fait est que vous n'aurez pas beaucoup d'instances du même objet Hibernate.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top