Pregunta

¿Hay alguna forma de usar objetos Flyweight con el mapeo de persistencia en hibernación? Mi modelo de datos contiene muchos objetos que serán iguales. En lugar de tener una instancia separada para cada uno de esos mismos objetos, me gustaría usar el patrón de diseño Flyweight y hacer referencia siempre al mismo objeto físico. ¿Cómo lograr esto en hibernación?

Por cierto. ¿todas las JVM optimizan el uso de cadenas de manera tal que cuando se usa la misma cadena varias veces, siempre será la misma instancia física?

¿Fue útil?

Solución

Depende.

Para valores de solo lectura, puede implementar fácilmente un patrón de peso mosca creando un UserType personalizado que devolverá objetos de un grupo en lugar de nuevas instancias cada vez.

Para las entidades, Hibernate es, por defecto, cuerdo y quiere ser coherente en todas las transacciones y, por lo tanto, no compartirá entidades entre Sesiones para evitar las condiciones de carrera de sus datos, y no creo que eso sea lo que desea.

Pero en caso de que sea (y esto no es totalmente recomendable sin saber realmente lo que está haciendo) puede implementar Interceptor.getEntity (), que está destinado al almacenamiento en caché de segundo nivel. En ese método, puede devolver una entidad (incluso algunas compartidas por otras sesiones) y efectivamente tendrá un patrón de peso mosca para sus entidades.

PERO lo recomiendo en contra de esto por la consistencia de sus datos: es mucho mejor tener valores de peso mosca inmutables reales a los que hacen referencia las entidades que también probar y pesar las entidades reales.

Otros consejos

Sí, puede implementar el patrón Flyweight con Hibernate.

El patrón de peso mosca es una forma de minimizar el uso de memoria por instancia . La estrategia es compartir tanto estado como sea posible entre instancias de peso mosca. En su caso, el estado que se puede compartir es todo excepto el identificador de objeto de hibernación y algún estado adicional para mantener la identidad del objeto .

Cada instancia de flyweight necesita su propia identidad del objeto . El estado adicional es la forma de implementar la identidad para distinguir entre objetos que comparten un estado común.

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

Si la identidad del objeto se comparte entre instancias, hibernate interpretaría todas las instancias físicas (referencias) como la misma instancia. Hibernate utiliza el método de igualdad para verificar la identidad del objeto y su implementación igual tendría que devolver (! A.equals (a) == true) que es ilegal. Igual tiene que ser reflexivo. Si rompe este contrato, se romperán todas las bibliotecas que dependen del contrato (colecciones, hibernación, etc.).

No puede implementar el método de igualdad utilizando el identificador de objeto de hibernación para distinguir entre objetos. Esto haría que la identidad del objeto dependiera del estado de persistencia (persistente o transitorio).

Una forma de modelar el estado común en hibernación es una asociación de uno a muchos entre objetos de estado compartido y objetos de peso mosca. (¿Quizás alguien tiene una idea de cómo mapear los datos sin unir dos tablas?)

Cadena: solo las cadenas internalizadas se compartirán. Esta no es la mejor solución la mayor parte del tiempo. Es apropiado para símbolos (nombre de clase, nombre de método, etc.). Las cadenas internalizadas nunca se recolectarán por basura y debe tener una instancia de String que se recolectará de todos modos new String (" .. "). Intern () . No guardará las asignaciones. Solo existe la pequeña ventaja de que la cadena base no sobrevivirá a una generación gc o podría asignarse en la pila (con el análisis de escape en el punto activo habilitado y aplicable).

  

¿todas las JVM optimizan el uso de cadenas de manera tal que cuando se usa la misma cadena varias veces, siempre será la misma instancia física?

Lo dudo mucho. En el mismo archivo de clase, cuando se define como:

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

probablemente tendrá s1 == s1.

Pero si tienes como:

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

No creo que el tiempo de ejecución compruebe y compare todas las cadenas cargadas con El valor de retorno de ellos constructor.

Entonces, siempre compara objetos con equals (). De todos modos, ese es un buen consejo ya que todo bien igual comienza con:

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

Si sus objetos implementan la igualdad por identidad, Hibernate solo tendrá la única instancia asociada con esa clave primaria. No creo que sea exactamente la misma idea que Flyweight, pero el punto es que no tendrás muchas instancias del mismo objeto Hibernate.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top