Una aplicación en la que estoy trabajando utiliza Hibernate exclusivamente para buscar en la memoria un grupo de objetos persistentes de una base de datos. La aplicación debe actualizar esta instantánea en memoria de la base de datos de vez en cuando, y esa debe ser la única comunicación con la base de datos.¿Cómo puedo cargar un conjunto Hibernate-mapped como un conjunto no modificable?
Los objetos en la memoria se utilizan para muchos cálculos. Los cálculos no deben modificar estos objetos. Excepto por alguna clase en algún lugar accidentalmente, y tuve que pasar un día buscando el error. Ahora me pregunto cuál es la mejor forma de hacer que todo el árbol de objetos sea inmutable.
Supongamos que la jerarquía de clases es el siguiente:
public class Building { // persistent entity
private String name; // hibernate-mapped property
private Set<Person> inhabitants; // hibernate-mapped collection
// getters
}
public class Person { // persistent entity
private String name; // hibernate-mapped property
// getters
}
he impedido clientes accedan a la base de datos:
- ir a buscar ansiosamente todas las entidades y colecciones
- marcado todas las entidades y colecciones con
mutable=false
en las asignaciones de Hibernate - sin proporcionar ninguna instancia de la sesión de Hibernate, o cambio de estado g dao métodos.
Ahora el error que me gustaría evitar es que alguien vaya accidentalmente a building.getInhabitants().clear();
. No puedo pensar en estas opciones:
Getter envolver: Hacer
getInhabitants
primera envolturainhabitants
en una llamadaCollections.unmodifiableSet()
, después lo devuelve.- Pros: el trabajo menos, código de menos adicional
- Contras: Se siente hacky
clases Wrapper: Cambiar el nombre de
Building
-MutableBuilding
,Person
-MutablePerson
, y proporcionan clases inmutablesBuilding
yPerson
. Como mi aplicación tiene un punto de instantánea claro, puedo buscar los registros como objetos mutables (como lo hago ahora), hacer copias profundamente inmutables y presentar ese árbol de objetos a los clientes.- Pros: Straight java, no Hibernate magic. Puedo usar mi palabra clave favorita:
final
- Contras: Más código para escribir y mantener. Además, ¿Hibernate mantendrá las instancias mutables en la memoria?
- Pros: Straight java, no Hibernate magic. Puedo usar mi palabra clave favorita:
Hibernate mapeo magia: usar que una palabra clave mágica para instruir a Hibernate para envolver las colecciones que se pone en mis objetos de entidad en
Collections.unmodifiableSet()
o equivalente.(Nota: Yo uso un archivo de asignación XML)- Pros: elegante, sin código adicional
- Contras: Esta palabra clave puede no existir
extensión Hibernate: Use que una extensión de hibernación apuntar para escribir mi propio instanciador de objetos, y allí envolver el conjunto en
Collections.unmodifiableSet()
antes de devolverlo.- Pros: Más elegante que la piratería mis captadores
- Contras: Tal punto de extensión puede no existir
En este momento me estoy inclinando hacia nº 2, sobre todo porque no hago saber si 3 y 4 son posibles.
¿Cuál es la mejor manera?
+1 por recordarme por qué escribimos getters y setters :-) – KarlP
Esto parece ser la mejor solución. ¡Tendré que aceptar el hecho de que las clases mutables a veces están bien! :) – oksayt