Anotaciones de hibernación: ¿cuál es el mejor acceso de campo o propiedad?

Respuestas:

33

Prefiero los accesores, ya que puedo agregar algo de lógica empresarial a mis accesores cuando lo necesito. Aquí hay un ejemplo:

@Entity
public class Person {

  @Column("nickName")
  public String getNickName(){
     if(this.name != null) return generateFunnyNick(this.name);
     else return "John Doe";
  }
}

Además, si agrega otras librerías a la mezcla (como una lib de conversión JSON o BeanMapper o Dozer u otra libra de mapeo / clonación de beans basada en las propiedades getter / setter) tendrá la garantía de que la lib está sincronizada con la persistencia manager (ambos usan getter / setter).

Miguel Ping
fuente
17
Tenga en cuenta que esto se trata de cómo el ORM accede a sus campos / propiedades y no a su código de aplicación. Con el acceso de campo, su método getNickName () funcionaría exactamente como esperaría. Lo mismo no es cierto si usa las 'propiedades' persistentes fuera de getters / setters. Ahí es donde puede encontrar problemas con el acceso a la propiedad y la carga lenta. Entonces no, no estoy de acuerdo con este argumento en general. Sin embargo, la última vez que verifiqué que Hibernate tenía problemas con el acceso a los campos @Id.
Rob Bygrave
11
Esta respuesta no está relacionada con la pregunta. Mejor respuesta por duffymo
Janning
9
no debería haber ninguna lógica de negocios dentro de los accesores. Ese no es un comportamiento obvio.
iuriisusuk
¿Por qué esta respuesta marca como correcta? No es cierto que pueda mapear el campo y proporcionarle un setter / getter de la misma manera.
Lucke
246

Hay argumentos para ambos, pero la mayoría de ellos se derivan de ciertos requisitos del usuario "¿y si necesita agregar lógica para" o "xxxx rompe la encapsulación". Sin embargo, nadie realmente ha comentado sobre la teoría y ha dado un argumento debidamente razonado.

¿Qué hace realmente Hibernate / JPA cuando persiste un objeto? Bueno, persiste el ESTADO del objeto. Eso significa almacenarlo de manera que pueda reproducirse fácilmente.

¿Qué es la encapsulación? Encapsulaciones significa encapsular los datos (o estado) con una interfaz que la aplicación / cliente puede usar para acceder a los datos de manera segura, manteniéndolos consistentes y válidos.

Piense en esto como MS Word. MS Word mantiene un modelo del documento en la memoria: los documentos ESTADO. Presenta una interfaz que el usuario puede usar para modificar el documento: un conjunto de botones, herramientas, comandos de teclado, etc. Sin embargo, cuando elige persistir (Guardar) ese documento, guarda el estado interno, no el conjunto de pulsaciones de teclas y clics del mouse utilizados para generarlo.

Guardar el estado interno del objeto NO interrumpe la encapsulación; de lo contrario, realmente no comprende lo que significa la encapsulación y por qué existe. Es como la serialización de objetos realmente.

Por esta razón, EN LA MAYORÍA DE LOS CASOS, es apropiado persistir en los CAMPOS y no en los ACCESORIOS. Esto significa que un objeto se puede recrear con precisión desde la base de datos exactamente de la manera en que se almacenó. No debería necesitar ninguna validación, porque esto se hizo en el original cuando se creó, y antes de que se almacenara en la base de datos (a menos, ¡Dios no lo quiera, está almacenando datos no válidos en el DB!). Del mismo modo, no debería ser necesario calcular valores, ya que ya se calcularon antes de que se almacenara el objeto. El objeto debe verse exactamente igual que antes de guardarlo. De hecho, al agregar cosas adicionales a los captadores / establecedores, en realidad está aumentando el riesgo de recrear algo que no sea una copia exacta del original.

Por supuesto, esta funcionalidad se agregó por una razón. Puede haber algunos casos de uso válidos para persistir los accesos, sin embargo, generalmente serán raros. Un ejemplo puede ser que desee evitar la persistencia de un valor calculado, aunque es posible que desee hacer la pregunta de por qué no lo calcula a pedido en el captador del valor, o lo inicializa perezosamente en el captador. Personalmente, no puedo pensar en ningún buen caso de uso, y ninguna de las respuestas aquí realmente da una respuesta de "Ingeniería de software".

Martín
fuente
9
La respuesta de ingeniería de software es: el uso de accesores viola DRY.
sourcedelica
1
@ Martin Tengo una pregunta de seguimiento sobre el último párrafo de su respuesta. Usted escribió "Un ejemplo puede ser que desea evitar la persistencia de un valor calculado". ¿Cómo puede evitar persistir en un valor calculado al tener acceso basado en la propiedad? Sé que estás discutiendo por no hacerlo, pero no entiendo el punto aquí. ¿Puede usted explicar por favor?
Geek
44
@ Geek Ahora que lo leí, no estoy del todo seguro. Han pasado dos años desde que escribí esta respuesta. Supongo que un mejor ejemplo podría ser donde está trabajando con una base de datos heredada, y los datos se presentan de una manera diferente a su modelo de objetos: los accesores podrían proporcionar un mapeo entre los dos.
Martin
23
Un buen caso de uso para los accesores de mapeo es cuando necesita agregar información de mapeo a subclases de clases de entidades de terceros que no están vinculadas a ninguna implementación de persistencia. Como los campos son privados en esas clases, debe anular los accesos y agregarles anotaciones de mapeo. Otra opción sería utilizar el mapeo XML, pero algunas cosas son muy difíciles de hacer allí. Entonces, si desea anotaciones y asignar clases de terceros, subclasificarlas y agregar anotaciones en los accesos es el camino a seguir.
Elnur Abdurrakhimov
55
@ElnurAbdurrakhimov allá vamos, un excelente ejemplo. Gracias.
Martin
79

Prefiero el acceso al campo, porque de esa manera no estoy obligado a proporcionar getter / setter para cada propiedad.

Una encuesta rápida a través de Google sugiere que el acceso de campo es la mayoría (por ejemplo, http://java.dzone.com/tips/12-feb-jpa-20-why-accesstype ).

Creo que el acceso al campo es el idioma recomendado por Spring, pero no puedo encontrar una referencia que lo respalde.

Hay una pregunta SO relacionada que trató de medir el rendimiento y llegó a la conclusión de que "no hay diferencia".

duffymo
fuente
si no proporciona un setter getter en la entidad, ¿cuál es el uso de ese campo ... no puede usarlo en ninguna parte de la aplicación, porque los campos son privados
anshulkatta
1
¿No es una mala práctica proporcionar un captador y definidor para sus campos ?, supongo que mi comentario aquí no siempre es correcto, ya que estaba asumiendo un campo público, mientras que obviamente podría ser un campo privado al que nunca se accede.
Mathijs Segers
3
@anshulkatta Creo que realmente debería abordar sus preguntas, ya que de eso se trata la encapsulación. Idealmente, todos sus campos deberían ser privados y, si es posible, no deberían tener captadores o establecedores, ese es el mejor nivel de encapsulación que puede esperar. Considere un corrector de contraseña. 2 campos privados passwordHash y errorAttempts. Ambos pueden ser privados sin getter o setter. Son utilizados por bool checkPassword (contraseña de cadena) que hace un hash, comprueba contra passwordHash y luego actualiza FateAttempts y devuelve un resultado. No es necesario que otro código acceda a esos dos campos.
Martin
2
@anshulkatta Cabe señalar que en OOP, los captadores y los establecedores son un antipatrón, provienen de la programación de procedimientos, tener una clase con ellos rompe el principio de encapsulación y genera una gran cantidad de código repetitivo, es decir, el mismo tipo de código repetido una y otra vez. Los objetos deben ser inmutables, si se requiere la modificación de sus propiedades, debe hacerse a través de un método que haga algo más que simplemente devolver el valor de la propiedad.
Uriel Arvizu
No tan. "Anti-patrón" en este caso es una cuestión de opinión, no un dogma. Dicho esto, todavía se prefiere el acceso al campo. Una mejor idea es evitar las soluciones ORM por completo. Aprenda a escribir SQL adecuado.
duffymo
38

Aquí hay una situación en la que TIENE que usar accesores de propiedad. Imagine que tiene una clase abstracta GENÉRICA con mucha bondad de implementación para heredar en 8 subclases concretas:

public abstract class Foo<T extends Bar> {

    T oneThing;
    T anotherThing;

    // getters and setters ommited for brevity

    // Lots and lots of implementation regarding oneThing and anotherThing here
 }

¿Ahora exactamente cómo debe anotar esta clase? La respuesta es que NO PUEDE anotarlo en absoluto con acceso a campos o propiedades porque no puede especificar la entidad objetivo en este momento. Tienes que anotar las implementaciones concretas. Pero como las propiedades persistentes se declaran en esta superclase, DEBE utilizar el acceso a la propiedad en las subclases.

El acceso de campo no es una opción en una aplicación con superclases genéricas abstractas.

HDave
fuente
2
Touche No había pensado en eso. Apuesto a que Hibernate lanza algunos sql locos por estos.
Joseph Lust
8
Este problema parece mecánicamente difícil de resolver sin anotar propiedades, pero nunca me he encontrado con un caso en el que necesitaba una clase genérica abstracta con mucha implementación que también quisiera persistir. Por lo general, creo una jerarquía de clases para hacer que mi objeto sea polimórfico (lo que lo convierte en una especie de interrupción genérica), y no solo para la reutilización del código. Y "mucha, mucha implementación" a menudo viola SRP de todos modos, en cuyo caso probablemente lo movería a clases separadas. ¿Hay algún ejemplo concreto que haga que este caso de uso sea más obvio?
Merlyn Morgan-Graham
El único ejemplo concreto que tengo es mi aplicación, que no puedo describir en un comentario de 500 caracteres ;-)
HDave
3
Puede usar abstract T getOneThing(), y abstract void setOneThing(T thing), y usar el acceso de campo.
Arturo Volpe
33

Tiendo a preferir y usar accesores de propiedad:

  • Puedo agregar lógica si surge la necesidad (como se menciona en la respuesta aceptada).
  • me permite llamar foo.getId() sin inicializar un proxy (importante cuando utilizo Hibernate, hasta que se resuelva HHH-3718 ).

Retirarse:

  • hace que el código sea menos legible, por ejemplo, debe examinar toda una clase para ver si hay @Transientpor ahí.
Pascal Thivent
fuente
pero si usa un proveedor de JPA que no tiene "poderes", entonces no tiene ese problema, también conocido como "su proveedor de JPA le está imponiendo".
Neil Stockton el
13

Eso realmente depende de un caso específico: ambas opciones están disponibles por una razón. En mi opinión, se reduce a tres casos:

  1. setter tiene cierta lógica que no debe ejecutarse al momento de cargar una instancia desde una base de datos; por ejemplo, una validación de valor ocurre en el setter, sin embargo, los datos que provienen de db deberían ser válidos (de lo contrario no llegarían allí (:); en este caso, el acceso al campo es el más apropiado;
  2. setter tiene alguna lógica que siempre debe invocarse, incluso durante la carga de una instancia desde db; por ejemplo, la propiedad que se inicializa se usa en el cálculo de algún campo calculado (por ejemplo, propiedad - una cantidad monetaria, propiedad calculada - un total de varias propiedades monetarias de la misma instancia); en este caso se requiere acceso a la propiedad.
  3. Ninguno de los casos anteriores: entonces ambas opciones son aplicables, solo manténgase constante (si el acceso al campo es la opción en esta situación, úsela todo el tiempo en una situación similar).
01es
fuente
Soy nuevo en Hibernate y estoy luchando con la misma pregunta. Creo que esta publicación proporciona la respuesta más clara. Gracias.
Sam Levin
12

Recomiendo encarecidamente el acceso al campo y NO las anotaciones en los captadores (acceso a la propiedad) si desea hacer algo más en los establecedores que solo establecer el valor (por ejemplo, Cifrado o cálculo).

El problema con el acceso a la propiedad es que también se llama a los establecedores cuando se carga el objeto. Esto me funcionó bien durante muchos meses hasta que quisimos introducir el cifrado. En nuestro caso de uso, queríamos cifrar un campo en el setter y descifrarlo en el getter. El problema ahora con el acceso a la propiedad era que cuando Hibernate cargaba el objeto, también llamaba al configurador para llenar el campo y, por lo tanto, encriptaba el valor encriptado nuevamente. Esta publicación también menciona esto: Java Hibernate: comportamiento de función de conjunto de propiedades diferente dependiendo de quién lo llame

Esto me ha causado dolores de cabeza hasta que recordé la diferencia entre el acceso al campo y el acceso a la propiedad. Ahora he movido todas mis anotaciones del acceso a la propiedad al acceso al campo y ahora funciona bien.

Christoph
fuente
Sí, he descubierto que si usa el acceso a la propiedad, realmente no puede hacer nada en su setter además de establecer el valor del campo.
HDave
2
+1 Mantener alejado de captadores / colocadores. Uso projectlombok.org y los mantengo ocultos para los desarrolladores.
Bhantol
11

Prefiero usar el acceso de campo por las siguientes razones:

  1. El acceso a la propiedad puede generar errores muy desagradables al implementar equals / hashCode y hacer referencia a campos directamente (a diferencia de sus captadores). Esto se debe a que el proxy solo se inicializa cuando se accede a los captadores, y un acceso de campo directo simplemente devolvería nulo.

  2. El acceso a la propiedad requiere que anote todos los métodos de utilidad (por ejemplo, addChild / removeChild) como @Transient.

  3. Con el acceso al campo, podemos ocultar el campo @Version al no exponer un captador en absoluto. Un getter también puede llevar a agregar un setter, y el versioncampo nunca debe establecerse manualmente (lo que puede generar problemas muy desagradables). Todo el incremento de la versión debe activarse mediante el bloqueo explícito OPTIMISTIC_FORCE_INCREMENT o PESSIMISTIC_FORCE_INCREMENT .

Vlad Mihalcea
fuente
1. ¿Cómo previene esto la estrategia de acceso de campo? Esto parece ser un obstáculo general con los servidores proxy, independientemente del estilo de acceso. 2. ¿Estás seguro de que solo deberían ser usuarios de servicios públicos? (Pero un buen argumento de todos modos). 3. Exponer accesores para el versioncampo a menudo es útil en situaciones en las que se usan DTO en lugar de entidades separadas.
Dragan Bozanovic
1. Debido a cuando se inicializa un Proxy. 2. 100% seguro. 3. Ese es un punto válido.
Vlad Mihalcea
Disculpe mi ignorancia y la posible falta de interpretación de texto (no soy hablante nativo de inglés). Solo para aclarar, el acceso al campo es cuando no se necesitan métodos getter / setter, entonces, para un POJO, que es holístico, ¿los campos son públicos? Pero usted dice algo en el primer tema y la publicación del blog vinculada dice lo contrario. Lo que sí entendí fue que no puedes usar iguales cuando utilizas proxies y acceso de campo.
MaikoID
No. El acceso al campo significa que Hibernate usa los campos a través de reflexiones para leer los atributos de la entidad. Para obtener más detalles, consulte la sección Tipo de acceso en la Guía del usuario de Hibernate .
Vlad Mihalcea
7

Creo que anotar la propiedad es mejor porque la actualización de los campos directamente interrumpe la encapsulación, incluso cuando su ORM lo hace.

Aquí hay un gran ejemplo de dónde te quemará: probablemente quieras tus anotaciones para el validador de hibernación y la persistencia en el mismo lugar (campos o propiedades). Si desea probar las validaciones activadas por su validador de hibernación que están anotadas en un campo, no puede usar una simulación de su entidad para aislar su prueba de unidad solo para el validador. Ay.

Justin Standard
fuente
2
Es por eso que coloca anotaciones de validación en los accesores y anotaciones de persistencia en los campos
espina de pescado
6

Creo que el acceso a la propiedad frente al acceso al campo es sutilmente diferente con respecto a la inicialización diferida.

Considere las siguientes asignaciones para 2 beans básicos:

<hibernate-mapping package="org.nkl.model" default-access="field">
  <class name="FieldBean" table="FIELD_BEAN">
    <id name="id">
      <generator class="sequence" />
    </id>
    <property name="message" />
  </class>
</hibernate-mapping>

<hibernate-mapping package="org.nkl.model" default-access="property">
  <class name="PropBean" table="PROP_BEAN">
    <id name="id">
      <generator class="sequence" />
    </id>
    <property name="message" />
  </class>
</hibernate-mapping>

Y las siguientes pruebas unitarias:

@Test
public void testFieldBean() {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    FieldBean fb = new FieldBean("field");
    Long id = (Long) session.save(fb);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    fb = (FieldBean) session.load(FieldBean.class, id);
    System.out.println(fb.getId());
    tx.commit();
    session.close();
}

@Test
public void testPropBean() {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    PropBean pb = new PropBean("prop");
    Long id = (Long) session.save(pb);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    pb = (PropBean) session.load(PropBean.class, id);
    System.out.println(pb.getId());
    tx.commit();
    session.close();
}

Verá la sutil diferencia en las selecciones requeridas:

Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        FIELD_BEAN
        (message, id) 
    values
        (?, ?)
Hibernate: 
    select
        fieldbean0_.id as id1_0_,
        fieldbean0_.message as message1_0_ 
    from
        FIELD_BEAN fieldbean0_ 
    where
        fieldbean0_.id=?
0
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        PROP_BEAN
        (message, id) 
    values
        (?, ?)
1

Es decir, llamar fb.getId()requiere una selección, mientras pb.getId()que no.

kit de herramientas
fuente
¡Esto es divertido! :) Pero estoy seguro de que es un comportamiento específico de implementación. I
Vladimir Dyuzhev
Sí, supongo que esto se debe al hecho de que solo las clases persistentes están instrumentadas. Sin embargo, es una pena porque el campo de identificación es a menudo el único campo que no tiene valor comercial y no necesitaría ningún descriptor de acceso.
Maurice Perry el
6

Permítanme tratar de resumir las razones más importantes para elegir el acceso basado en el campo. Si desea profundizar más, lea este artículo en mi blog: Estrategias de acceso en JPA e Hibernate: ¿cuál es mejor, el acceso al campo o a la propiedad?

El acceso basado en el campo es, con mucho, la mejor opción. Aquí hay 5 razones para ello:

Razón 1: mejor legibilidad de su código

Si utiliza el acceso basado en campos, anota los atributos de su entidad con sus anotaciones de mapeo. Al colocar la definición de todos los atributos de entidad en la parte superior de su clase, obtiene una vista relativamente compacta de todos los atributos y sus asignaciones.

Razón 2: Omita los métodos getter o setter que su aplicación no debería invocar

Otra ventaja del acceso basado en el campo es que su proveedor de persistencia, por ejemplo, Hibernate o EclipseLink, no utiliza los métodos getter y setter de los atributos de su entidad. Eso significa que no necesita proporcionar ningún método que su código comercial no deba utilizar. Este suele ser el caso de los métodos de establecimiento de atributos de clave primaria generados o columnas de versión. Su proveedor de persistencia gestiona los valores de estos atributos, y no debe establecerlos mediante programación.

Razón 3: implementación flexible de los métodos getter y setter

Debido a que su proveedor de persistencia no llama a los métodos getter y setter, no está obligado a cumplir ningún requisito externo. Puede implementar estos métodos de la forma que desee. Eso le permite implementar reglas de validación específicas del negocio, activar una lógica comercial adicional o convertir el atributo de la entidad en un tipo de datos diferente.

Puede, por ejemplo, usar eso para envolver una asociación o atributo opcional en un Java Optional.

Razón 4: no es necesario marcar los métodos de utilidad como @Transient

Otro beneficio de la estrategia de acceso basado en el campo es que no necesita anotar sus métodos de utilidad @Transient. Esta anotación le dice a su proveedor de persistencia que un método o atributo no es parte del estado persistente de la entidad. Y debido a que con el acceso de tipo campo, el estado persistente se define por los atributos de su entidad, su implementación JPA ignora todos los métodos de su entidad.

Razón 5: evitar errores al trabajar con proxies

Hibernate usa proxies para asociaciones uno-vagamente obtenidas para que pueda controlar la inicialización de estas asociaciones. Ese enfoque funciona bien en casi todas las situaciones. Pero presenta un peligro peligroso si utiliza el acceso basado en la propiedad.

Si usa acceso basado en propiedades, Hibernate inicializa los atributos del objeto proxy cuando llama al método getter. Ese es siempre el caso si usa el objeto proxy en su código comercial. Pero bastante implementaciones igual y hashCode acceden a los atributos directamente. Si es la primera vez que accede a alguno de los atributos proxy, estos atributos aún no se han inicializado.

Thorben Janssen
fuente
3

De forma predeterminada, los proveedores de JPA acceden a los valores de los campos de entidad y asignan esos campos a las columnas de la base de datos utilizando los métodos de acceso de propiedad JavaBean (getter) y de mutador (setter) de la entidad. Como tal, los nombres y tipos de los campos privados en una entidad no son importantes para JPA. En cambio, JPA solo analiza los nombres y tipos de retorno de los accesores de propiedad JavaBean. Puede modificar esto mediante la @javax.persistence.Accessanotación, que le permite especificar explícitamente la metodología de acceso que debe utilizar el proveedor de JPA.

@Entity
@Access(AccessType.FIELD)
public class SomeEntity implements Serializable
{
...
}

Las opciones disponibles para la enumeración AccessType son PROPIEDAD (el valor predeterminado) y CAMPO. Con PROPIEDAD, el proveedor obtiene y establece valores de campo utilizando los métodos de propiedad JavaBean. FIELD hace que el proveedor obtenga y establezca valores de campo utilizando los campos de instancia. Como práctica recomendada, debe seguir con el valor predeterminado y usar las propiedades JavaBean a menos que tenga una razón convincente para hacerlo de otra manera.

Puede colocar estas anotaciones de propiedad en los campos privados o en los métodos de acceso público. Si usa AccessType.PROPERTY(predeterminado) y anota los campos privados en lugar de los accesores JavaBean, los nombres de los campos deben coincidir con los nombres de las propiedades JavaBean. Sin embargo, los nombres no tienen que coincidir si anota los accesores JavaBean. Del mismo modo, si usa AccessType.FIELDy anota los accesores JavaBean en lugar de los campos, los nombres de los campos también deben coincidir con los nombres de las propiedades JavaBean. En este caso, no tienen que coincidir si anota los campos. Es mejor ser coherente y anotar los accesores JavaBean AccessType.PROPERTYy los campos para AccessType.FIELD.

Es importante que nunca mezcle anotaciones de propiedad JPA y anotaciones de campo JPA en la misma entidad. Hacerlo da como resultado un comportamiento no especificado y es muy probable que cause errores.

Faraz
fuente
2

Ya llegamos

Esa es una presentación antigua, pero Rod sugiere que las anotaciones sobre el acceso a la propiedad alientan los modelos de dominio anémico y no deberían ser la forma "predeterminada" de anotar.

Manuel Palacio
fuente
2

Otro punto a favor del acceso al campo es que, de lo contrario, se verá obligado a exponer los establecedores para las colecciones, lo que, para mí, es una mala idea, ya que cambiar la instancia de colección persistente a un objeto no administrado por Hibernate definitivamente romperá la consistencia de sus datos.

Por lo tanto, prefiero tener colecciones como campos protegidos inicializados para implementaciones vacías en el constructor predeterminado y exponer solo sus captadores. Las operaciones a continuación, sólo se maneja como clear(), remove(), removeAll()es posible que nunca se hará Hibernate conscientes de los cambios, etc.

Jiří Vypědřík
fuente
No está obligado a exponer nada, ya que los setters pueden protegerse. Además, esos configuradores no son parte de la interfaz que se está implementando, por lo que incluso si fueran públicos, no son fácilmente accesibles.
HDave
2

Prefiero los campos, pero me he encontrado con una situación que parece obligarme a colocar las anotaciones en los captadores.

Con la implementación Hibernate JPA, @Embeddedno parece funcionar en los campos. Así que eso tiene que irse por sorpresa. Y una vez que lo pones en el captador, las diversas @Columnanotaciones también tienen que ir a los captadores . (Creo que Hibernate no quiere mezclar campos y captadores aquí.) Y una vez que se ponen @Columncaptadores en una clase, probablemente tenga sentido hacerlo todo el tiempo.


fuente
2

Estoy a favor de los accesores de campo. El código es mucho más limpio. Todas las anotaciones se pueden colocar en una sección de una clase y el código es mucho más fácil de leer.

Encontré otro problema con los accesores de propiedades: si tiene métodos getXYZ en su clase que NO están anotados como asociados con propiedades persistentes, hibernate genera sql para intentar obtener esas propiedades, lo que resulta en algunos mensajes de error muy confusos. Dos horas desperdiciadas. No escribí este código; Siempre he usado accesores de campo en el pasado y nunca me he encontrado con este problema.

Versiones de Hibernate utilizadas en esta aplicación:

<!-- hibernate -->
<hibernate-core.version>3.3.2.GA</hibernate-core.version>
<hibernate-annotations.version>3.4.0.GA</hibernate-annotations.version>
<hibernate-commons-annotations.version>3.1.0.GA</hibernate-commons-annotations.version>
<hibernate-entitymanager.version>3.4.0.GA</hibernate-entitymanager.version>
John Goyer
fuente
2

Debe elegir el acceso a través de campos sobre el acceso a través de propiedades. Con los campos puede limitar los datos enviados y recibidos. Con las propiedades via, puede enviar más datos como host y establecer denominaciones G (que configuran de fábrica la mayoría de las propiedades en total).

usuario10801787
fuente
1

Creamos beans de entidad y utilizamos anotaciones getter. El problema con el que nos encontramos es el siguiente: algunas entidades tienen reglas complejas para algunas propiedades con respecto a cuándo se pueden actualizar. La solución fue tener cierta lógica de negocios en cada setter que determina si el valor real cambió o no y, de ser así, si el cambio debería permitirse. Por supuesto, Hibernate siempre puede establecer las propiedades, por lo que terminamos con dos grupos de establecedores. Muy feo.

Al leer publicaciones anteriores, también veo que hacer referencia a las propiedades desde el interior de la entidad podría generar problemas con las colecciones que no se cargan.

En pocas palabras, me inclinaría hacia la anotación de los campos en el futuro.

Steve11235
fuente
0

Normalmente los frijoles son POJO, por lo que tienen accesores de todos modos.

Entonces, la pregunta no es "¿cuál es mejor?", Sino simplemente "¿cuándo usar el acceso de campo?". Y la respuesta es "cuando no necesita un setter / getter para el campo!".

Vladimir Dyuzhev
fuente
44
El problema es que no puede mezclar el acceso de campo y el acceso a la propiedad en un POJO: debe elegir uno
Martin OConnor
De Verdad? Debo haberlo olvidado. De todos modos, siempre uso los accesorios POJO y d.
Vladimir Dyuzhev 01 de
Tenga en cuenta que con JPA 2.0 (que no existía cuando se hizo esta pregunta) ahora puede mezclar tipos de acceso utilizando la anotación @AccessType.
mtpettyp
0

Estoy pensando en esto y elijo el método de acceso

¿por qué?

porque el campo y el acceso al método son los mismos, pero si luego necesito algo de lógica en el campo de carga, guardo mover todas las anotaciones colocadas en los campos

Saludos

Grubhart

usuario261548
fuente
0

Para que sus clases sean más limpias, coloque la anotación en el campo y luego use @Access (AccessType.PROPERTY)

ely
fuente
0

AccessType.PROPERTY: la implementación de persistencia EJB cargará el estado en su clase a través de métodos "setter" de JavaBean y recuperará el estado de su clase usando métodos "getter" de JavaBean. Este es el valor predeterminado.

AccessType.FIELD: el estado se carga y se recupera directamente de los campos de su clase. No tiene que escribir JavaBean "getters" y "setters".

Daria Yu
fuente