2008-11-20 9 views
21

Tengo lo que creo que es una pregunta simple. He visto ejemplos en ambos sentidos. La pregunta es: "¿por qué no puedo colocar mis anotaciones en el campo?". Déjeme darle un ejemplo ....Hibernate Annotation Placement Pregunta

@Entity 
@Table(name="widget") 
public class Widget { 
private Integer id; 

@Id 
@GeneratedValue(strategy=GenerationType.AUTO) 
public Integer getId() { return this.id; } 
public Integer setId(Integer Id) { this.id = id;} 
} 

El código anterior funciona bien (suponiendo que no hay un error tipográfico en allí). Cuando la anotación se coloca en el captador de la propiedad, todo es perfecto.

Sin embargo, eso me parece incómodo. En mi mente está más limpia para colocar la anotación en el campo, al igual que -

@Entity 
@Table(name="widget") 
public class Widget { 
@Id 
@GeneratedValue(strategy=GenerationType.AUTO) 
private Integer id; 

public Integer getId() { return this.id; } 
public Integer setId(Integer Id) { this.id = id;} 
} 

que he visto ejemplos de ambas maneras. Sin embargo, cuando ejecuto este segundo ejemplo me sale el siguiente ...

 
java.lang.NullPointerException 
    at com.widget.util.hibernate.HibernateSessionFactory$ThreadLocalSession.initialValue(HibernateSessionFactory.java:25) 
    at com.widget.util.hibernate.HibernateSessionFactory$ThreadLocalSession.initialValue(HibernateSessionFactory.java:1) 
    at java.lang.ThreadLocal$ThreadLocalMap.getAfterMiss(Unknown Source) 
    at java.lang.ThreadLocal$ThreadLocalMap.get(Unknown Source) 
    at java.lang.ThreadLocal$ThreadLocalMap.access$000(Unknown Source) 
    at java.lang.ThreadLocal.get(Unknown Source) 
    at com.widget.util.hibernate.HibernateSessionFactory.get(HibernateSessionFactory.java:33) 
    at com.widget.db.dao.AbstractDao.(AbstractDao.java:12) 
    at com.widget.db.dao.WidgetDao.(WidgetDao.java:9) 
    at com.widget.db.dao.test.WidgetDaoTest.findById(WidgetDaoTest.java:17) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    ... 

Aquí está el esqueleto de HibernateSessionFactory (línea 25 está marcada) ....

protected Session initialValue() { 
    SessionFactory sessionFactory = null; 
    try { 
     Configuration cfg = new AnnotationConfiguration().configure(); 
     String url = System.getProperty("jdbc.url"); 
     if (url != null) { 
      cfg.setProperty("hibernate.connection.url", url); 
     } 
     sessionFactory = cfg.buildSessionFactory(); 
    } 
    catch (Exception e) { 
    } 

    Session session = sessionFactory.openSession(); // LINE 25 
    return session; 
} 

Alguien tiene una idea de lo que está pasando ¿aqui?

+0

Tal vez usted está tragando una excepción en el bloque catch en la línea 22? – johnstok

Respuesta

31

Desde una perspectiva de rendimiento y diseño, usar anotaciones en getters es una mejor idea que las variables miembro, porque los setters getter se llaman usando reflexión si se colocan en el campo, que un método. Además, si planea usar la validación y otras funciones de hibernación, tendrá todas las anotaciones en un solo lugar, en lugar de dispersarlas por todos lados.

Mi recomendación es ir con métodos no variables de miembros.

De la documentación

Dependiendo de si realizar anotaciones campos o métodos, el tipo de acceso utilizado por Hibernate habrá campo o propiedad.La especificación EJB3 requiere que declare las anotaciones en el tipo de elemento al que se accederá, es decir, el método getter si utiliza el acceso a la propiedad, el campo si usa el acceso al campo. Debe evitarse mezclar anotaciones EJB3 en ambos campos y métodos. Hibernate adivinará el tipo de acceso desde la posición de @Id o @EmbeddedId.

+2

re: 'porque los setters getter se llaman usando reflection', ¿cuánto más lento? ¿Tiene una estimación aproximada de cuánto tiempo lleva usar Reflection en lugar del captador y colocador de un campo (s)? Gracias –

+3

Un voto negativo de mí ya que no respondió por qué el acceso de campo no funciona en el ejemplo de OP. Además, afirmas que hay una diferencia de velocidad, pero no la probaste. AFAIK, hibernate usa la reflexión ya sea que anote el campo o el método. También vea: stackoverflow.com/questions/332591 – Navin

+2

@Navin +1 http://stackoverflow.com/questions/332591 afirma que no hay una diferencia significativa en el rendimiento. – Torsten

0

¿funciona si lo hace lo siguiente:

@Entity 
@Table(name="widget") 
public class Widget { 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 

    private Integer id; 

    public Integer getId() { return this.id; } 
    public Integer setId(Integer Id) { this.id = id;} 
} 
+1

No. Si "por lo siguiente" se refiere a una línea en blanco después de @GeneratedValue. Mismo resultado. (¡Y gracias por esa respuesta rápida!). – SteveT

+0

No hay problema. Hubiera pensado que si configuras Hibernate programáticamente, deberás indicarle a AnnotationConfiguration dónde encontrar tus clases anotadas. Consulte lo siguiente: http://www.hibernate.org/hib_docs/annotations/reference/en/html_single/#setup-configuration – Jonathan

1

Un largo alcance, pero ¿Tiene una vieja *.hbm.xml archivo flotando?

¿Quizás podría elegir una configuración incorrecta para default-access y usar property en lugar de field?

10

Me has puesto en el camino correcto. Gracias. Aquí está el trato ... Por supuesto, mi ejemplo artificial no incluía toda la historia. Mi clase de Widget en realidad era mucho más grande que el ejemplo que di. Tengo varios campos/getters adicionales y estaba MIXING mis anotaciones. Así que estaba anotando @Id en el campo, pero otros estaban siendo anotados en el getter.

Así que la moraleja de la historia es que no se pueden mezclar las ubicaciones de las anotaciones. O bien todas las anotaciones están en los campos o están en los métodos getter. Long time Java and Hibernate, nuevo en Anotaciones. Aprende algo todos los días.

Una vez que supe lo que a Google por me encontré con este que era muy útil - http://chstath.blogspot.com/2007/05/field-access-vs-property-access-in-jpa.html

Por supuesto, esto ahora nos lleva a la pregunta de cuál es mejor desde el diseño y perspectivas de rendimiento.

+0

great .......... – nobalG

1

Este es un enlace muy bueno que puede ayudarlo a comprender los accesos y las mejores prácticas relacionadas.

Comprendiendo @AccessType in Hibernate

+0

Esta pregunta es un poco antigua, pero aquí hay un nuevo enlace que proporciona información valiosa y relevante: http://www.dzone.com/links/r/the_curious_case_case_of_field_and_property_access_in.html – SteveT

Cuestiones relacionadas