Question de positionnement d’annotation Hibernate

J’ai ce que je pense est une question simple. J’ai vu des exemples dans les deux sens. La question est: “pourquoi ne puis-je pas placer mes annotations sur le terrain?”. Laisse moi te donner un exemple….

@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;} } 

Le code ci-dessus fonctionne bien (en supposant qu’il n’y ait pas de faute de frappe ici). Lorsque l’annotation est placée sur le getter de la propriété, tout est parfait.

Cependant, cela me semble gênant. Dans mon esprit, il est plus propre de placer l’annotation sur le terrain, comme ça –

 @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;} } 

J’ai vu des exemples des deux manières. Cependant, lorsque je lance ce deuxième exemple, je reçois le texte suivant …

 java.lang.NullPointerException
     à l'adresse com.widget.util.hibernate.HibernateSessionFactory $ ThreadLocalSession.initialValue (HibernateSessionFactory.java:25)
     à l'adresse com.widget.util.hibernate.HibernateSessionFactory $ ThreadLocalSession.initialValue (HibernateSessionFactory.java:1)
     sur java.lang.ThreadLocal $ ThreadLocalMap.getAfterMiss (Source inconnue)
     sur java.lang.ThreadLocal $ ThreadLocalMap.get (Source inconnue)
     sur java.lang.ThreadLocal $ ThreadLocalMap.access $ 000 (source inconnue)
     at java.lang.ThreadLocal.get (Source inconnue)
     à com.widget.util.hibernate.HibernateSessionFactory.get (HibernateSessionFactory.java:33)
     sur com.widget.db.dao.AbstractDao. (AbstractDao.java:12)
     sur com.widget.db.dao.WidgetDao. (WidgetDao.java:9)
     at com.widget.db.dao.test.WidgetDaoTest.findById (WidgetDaoTest.java:17)
     à sun.reflect.NativeMethodAccessorImpl.invoke0 (méthode native)
     at sun.reflect.NativeMethodAccessorImpl.invoke (Source inconnue)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke (Source inconnue)
     at java.lang.reflect.Method.invoke (Source inconnue)
     ...

Voici le squelette de HibernateSessionFactory (la ligne 25 est marquée) ….

 protected Session initialValue() { SessionFactory sessionFactory = null; try { Configuration cfg = new AnnotationConfiguration().configure(); Ssortingng 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; } 

Quelqu’un a une idée de ce qui se passe ici?

Du sharepoint vue des performances et de la conception, l’utilisation des annotations sur les getters est une meilleure idée que les variables membres, car les règles de lecture sont appelées par reflection si elles sont placées sur le terrain, plutôt que par une méthode. De plus, si vous prévoyez d’utiliser la validation et d’autres fonctionnalités de la mise en veille prolongée, vous aurez toutes les annotations au même endroit, plutôt que de les disperser partout.

Ma recommandation va avec des méthodes non membres.

De la documentation

Selon que vous annotez des champs ou des méthodes, le type d’access utilisé par Hibernate sera le champ ou la propriété. La spécification EJB3 nécessite que vous déclariez des annotations sur le type d’élément auquel vous accéderez, c’est-à-dire la méthode d’accesseur en lecture si vous utilisez l’access aux propriétés, le champ si vous utilisez l’access aux champs. Le mélange d’annotations EJB3 dans les deux champs et méthodes doit être évité. Hibernate va deviner le type d’access à partir de la position @Id ou @EmbeddedId.

Vous m’avez mis sur la bonne voie. Merci. Voici le deal … Bien sûr, mon exemple artificiel n’incluait pas toute l’histoire. Ma classe de widgets était en réalité beaucoup plus volumineuse que l’exemple que j’ai donné. J’ai plusieurs champs / getters supplémentaires et je mixais mes annotations. J’annotais donc le @ Id sur le terrain, mais d’autres étaient annotés sur le getter.

Donc, la morale de l’histoire est que vous ne pouvez pas mélanger les emplacements d’annotation. Soit toutes les annotations sont sur les champs ou ils sont sur les méthodes getter. Long time Java et Hibernate, nouveau dans les annotations. Apprenez quelque chose tous les jours.

Une fois que j’ai su ce que Google cherchait, je suis tombé sur cette information qui était utile

Bien sûr, cela soulève maintenant la question de savoir quelles sont les meilleures outlook de conception et de performance.

Une longue scope, mais avez-vous un ancien fichier *.hbm.xml flotte?

Peut-être pourrait-il choisir le mauvais paramètre pour l’ default-access par default-access et utiliser la property au lieu du field ?

C’est un très bon lien qui peut vous aider à comprendre les types d’access et les meilleures pratiques en vigueur!

Comprendre @AccessType dans Hibernate

Cela fonctionne-t-il si vous procédez comme suit:

 @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;} }