Подтвердить что ты не робот

Вопрос о размещении аннотации Hibernate

У меня есть то, что я считаю простым вопросом. Я видел примеры в обоих направлениях. Вопрос в том, "почему я не могу разместить свои аннотации на поле?". Позвольте мне привести вам пример.

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

Приведенный выше код работает отлично (если там нет опечатки). Когда аннотация размещена на геттере свойства, все идеально.

Однако мне это кажется неудобным. На мой взгляд, это чище разместить аннотацию на поле, например:

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

Я видел примеры обоих способов. Однако, когда я запускаю этот второй пример, я получаю следующее...

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)
    ...

Здесь скелет HibernateSessionFactory (строка 25 отмечена)....

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

У кого-нибудь есть идея, что здесь происходит?

4b9b3361

Ответ 1

С точки зрения производительности и дизайна использование аннотаций на геттерах является лучшей идеей, чем переменные-члены, потому что сеттеры-получатели вызываются с использованием отражения, если они помещены в поле, чем метод. Также, если вы планируете использовать валидацию и другие функции спящего режима, вы будете иметь все аннотации в одном месте, а не рассеивать их повсюду.

Моя рекомендация касается методов, не являющихся переменными-членами.

Из документации

В зависимости от того, аннотируете ли вы поля или методы, тип доступа, используемый Hibernate, будет полем или свойством. Спецификация EJB3 требует, чтобы вы объявляли аннотации по типу элемента, к которому будут обращаться, т.е. Метод getter, если вы используете доступ к свойствам, поле, если вы используете доступ к полю. Следует избегать микширования аннотаций EJB3 в обоих полях и методах. Hibernate угадает тип доступа с позиции @Id или @EmbeddedId.

Ответ 2

Ты завел меня на верный трек. Благодарю. Здесь сделка... Конечно, мой надуманный пример не включал всю историю. Класс My Widget на самом деле намного больше, чем пример, который я дал. У меня есть несколько дополнительных полей/геттеров, и я был MIXING мои аннотации. Таким образом, я аннотировал @Id на поле, но другие были аннотированы на геттере.

Итак, мораль этой истории заключается в том, что вы не можете смешивать местоположения аннотаций. Либо все аннотации находятся на полях, либо они находятся на методах геттера. Долгое время Java и Hibernate, новые для Annotations. Учитесь чему-то каждый день.

Как только я знал, что для Google, я натолкнулся на это, что было полезно - http://chstath.blogspot.com/2007/05/field-access-vs-property-access-in-jpa.html

Конечно, теперь это поднимает вопрос о том, что лучше с точки зрения дизайна и производительности.

Ответ 3

Достаточно длинный, но есть ли у вас старый *.hbm.xml файл, плавающий вокруг?

Возможно, это может быть неправильная настройка для default-access и использование property вместо field?

Ответ 4

Это очень приятная ссылка, которая может помочь вам понять, что такое accesstypes и отличные рекомендации!

Understading @AccessType в спящем режиме

Ответ 5

Работает ли он, если вы выполняете следующее:

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