Вопрос о размещении аннотации в спящем режиме - PullRequest
22 голосов
/ 20 ноября 2008

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

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

Кто-нибудь имеет представление, что здесь происходит?

Ответы [ 5 ]

31 голосов
/ 21 ноября 2008

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

Я рекомендую использовать методы, не являющиеся переменными-членами.

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

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

11 голосов
/ 20 ноября 2008

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

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

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

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

1 голос
/ 27 апреля 2010

Это очень хорошая ссылка, которая может помочь вам в понимании accesstypes и соответствующих передовых методов!

Понимание @ AccessType в Hibernate

1 голос
/ 20 ноября 2008

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

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

0 голосов
/ 20 ноября 2008

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

@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;}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...