2010-03-16 12 views
5

Soy muy nuevo en Java, pero he estado desarrollando el hábito de usar final siempre que sea posible, declarando la inmutabilidad que creo que es algo bueno. (Considere f #)Proveedor de persistencia para Java que admite los campos finales

He leído que JPA no admite los campos finales. Hibernate, TopLink? No estoy seguro de esto, pero prefiero JPA por ahora.

¿Es eso posible incluso teóricamente, digamos a través de la reflexión, modificar los campos finales después de la creación? Mi suposición sería ... NO :)

Lo que sin duda sería posible para una solución de persistencia es apoyar constructores con parámetros. Al menos no veo ninguna razón que haría esto imposible. El mapeo sería un poco complicado, supongo. Esta es una solución alternativa.

Sugerencias?

EDIT: No estoy familiarizado con la definición exacta de inmutable, así que lo usé en esta publicación de manera intuitiva. Declarar la inmutabilidad aquí significa declarar que un campo no se puede cambiar. Perdón por el malentendido.

Respuesta

6

La inmutabilidad de objetos (observar la diferencia entre un objeto inmutable y declarar un campo final, un objeto SÓLO es inmutable si TODOS los campos son definitivos, por lo que el estado del objeto no puede cambiar después de la creación) es un tema muy delicado. Me gustan ellos mismos, e hibernate los apoya a través de @Imutable.

No conozco su estado en JPA 2, pero para responder a la pregunta sobre los campos finales: PUEDE cambiar sus valores usando reflexión, pero la reflexión es muy limitada en un entorno Java EE.

Para aclarar el problema principal: si sus POJO son inmutables, ¿cómo podría una solución persistente recrear los objetos? Supongamos que tiene dos campos int finales y un constructor para inicializarlos. La capa de persistencia no puede tener ninguna información sobre su orden o sus nombres (ya que los nombres de campo y de parámetros se borran durante la compilación).

Koshuke publicó un blog sobre esto (en relación con JAXB apoyando beans inmutables), pero no puede encontrarlo ahora.

-1

Honestamente, esta es una idea extraña.

al hacer campos final, se indica al compilador que van a Nunca cambio después de la creación de objetos. Como consecuencia, es una suposición razonable no persistir, ya que nunca cambiarán. Bueno, al escribir esto, supongo que tienes la cultura java, pero la pregunta que haces precisamente dice lo contrario.

En Java, los obejcts persistentes se "asume" siempre como POJO (en otras palabras, Java Beans). Un Java Bean debe tener (para ser considerado como tal) un constructor vacío que permita marcos de persistencia y demás para construirlo usando su constructor vacío, llamándolo indirectamente a través de Class.newInstance() /.

Existen campos en los que se utilizan constructores no vacíos (como contenedores IoC: Guice, Spring y IoC de Tapestry), pero están fuera del alcance de Java Beans, que deben considerarse objetos de datos.

+0

¿Qué tal una base de datos de solo lectura? Por cierto, estoy explorando posibilidades. – naeron84

+0

Otros casos de uso: entidad múltiple para una tabla. O crear esas entidades a través de un método de fábrica. – naeron84

1

Puede que esto no sea exactamente lo que estás buscando, pero el principio de inmutabilidad puede ser fácilmente respaldado por campos privados no finales que solo tienen un getter. De hecho, el compilador lo reconoce y genera un código que es prácticamente idéntico al que obtendría con los campos declarados como definitivos.

Esto requerirá que sea concienzudo y no cambie sus campos dentro de la clase contenedora (mientras que final haría cumplir eso), pero creo que este no es un gran precio a pagar por la flexibilidad que obtiene.

0

Los campos finales no se pueden modificar después de la creación por diseño. Hacer lo contrario es una muy mala idea, porque alguien puede confiar en el comportamiento estándar.

En general, los marcos de persistencia se ocupan de las jerarquías de los objetos "normales". Tiene objetos, que solo se pueden crear y eliminar, no modificar. Eso es muy extraño, porque cuando creas una entidad, creas algún tipo de identificación para ella. A través de esta identificación, usted conecta la entidad a otros. Cuando elimina una entidad antigua y crea otra, usted (en general) obtiene una entidad con otra ID. Entonces, todas las conexiones (claves externas) están rotas. ¿Es el comportamiento objetivo?

+0

Usted hace algunos puntos válidos; +1. –

1

Buena pregunta. En realidad, es una buena idea declarar campos como definitivos si no cambian (se obtienen las garantías de inicialización del JMM).

La APP Spec es clara con respecto a los campos finales:

clase La entidad no debe ser final. Ningún método variable de instancia persistente de la clase de entidad puede ser definitiva.

Hoever, no todas las implementaciones de seguir esta regla y el mango campos finales:

  • OpenJPA no admite campos finales, es decir, se les trata como transitorio. Al cargar, los campos finales de dicha entidad se inicializan con los valores como definidos en el constructor sin parámetros.

  • La implementación de Hibernate admite campos finales. En la construcción, los campos finales que se han inicializado en el constructor sin parámetros se reemplazan con los valores almacenados en la base de datos.

Así que para responder a su pregunta: Sí, hay proveedores de persistencia JPA que apoyan campos finales, sin embargo yo recomiendo no usar campos finales en sus clases de entidad como el comportamiento no está definido (y en realidad difiere de proveedor al proveedor). Además, creo que es una mala idea que un proveedor de JPA cambie los campos finales después de la construcción porque las garantías de visibilidad se pueden violar de esta manera.

Cuestiones relacionadas