2011-01-13 15 views
6

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:

  1. Getter envolver: Hacer getInhabitants primera envoltura inhabitants en una llamada Collections.unmodifiableSet(), después lo devuelve.

    • Pros: el trabajo menos, código de menos adicional
    • Contras: Se siente hacky
  2. clases Wrapper: Cambiar el nombre de Building-MutableBuilding, Person-MutablePerson, y proporcionan clases inmutables Building y Person. 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?
  3. 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
  4. 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?

Respuesta

6

Opción 1, seguro. No es "hacky", y eso es exactamente por lo que abstractaste el acceso a la propiedad en métodos, en primer lugar :-) Solo ten en cuenta que debes usar "acceso de campo" con Hibernate, en lugar de "método", para que no lo hagas el riesgo de proporcionar una colección no modificable a Hibernate.

Desafortunadamente, Hibernate no proporciona una forma de colocar colecciones no modificables, pero creo que puede hacer un detector de eventos @PostLoad para modificar todas las colecciones una vez que se carga el objeto.

+0

+1 por recordarme por qué escribimos getters y setters :-) – KarlP

+0

Esto parece ser la mejor solución. ¡Tendré que aceptar el hecho de que las clases mutables a veces están bien! :) – oksayt

Cuestiones relacionadas