24

我有一个我认为很简单的问题。我已经看到了两种方式的例子。问题是 - “为什么我不能将我的注释放在字段上?”。让我给你举个例子....

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

上面的代码工作正常(假设那里没有错字)。当注释放在属性的 getter 上时,一切都很完美。

然而,这对我来说似乎很尴尬。在我看来,将注释放在字段上会更干净,就像这样 -

@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
    在 com.widget.util.hibernate.HibernateSessionFactory$ThreadLocalSession.initialValue(HibernateSessionFactory.java:25)
    在 com.widget.util.hibernate.HibernateSessionFactory$ThreadLocalSession.initialValue(HibernateSessionFactory.java:1)
    在 java.lang.ThreadLocal$ThreadLocalMap.getAfterMiss(未知来源)
    在 java.lang.ThreadLocal$ThreadLocalMap.get(未知来源)
    在 java.lang.ThreadLocal$ThreadLocalMap.access$000(未知来源)
    在 java.lang.ThreadLocal.get(未知来源)
    在 com.widget.util.hibernate.HibernateSessionFactory.get(HibernateSessionFactory.java:33)
    在 com.widget.db.dao.AbstractDao.(AbstractDao.java:12)
    在 com.widget.db.dao.WidgetDao.(WidgetDao.java:9)
    在 com.widget.db.dao.test.WidgetDaoTest.findById(WidgetDaoTest.java:17)
    在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    在 sun.reflect.NativeMethodAccessorImpl.invoke(未知来源)
    在 sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)
    在 java.lang.reflect.Method.invoke(未知来源)
    ...

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

有人知道这里发生了什么吗?

4

5 回答 5

35

从性能和设计的角度来看,在 getter 上使用注解比成员变量更好,因为如果将 getter setter 放在字段上,则使用反射而不是方法调用。此外,如果您计划使用 hibernate 的验证和其他功能,您将在一个地方拥有所有注释,而不是将它们分散在一个地方。

我的建议是使用方法而不是成员变量。

从文档

根据您是否注释字段或方法,Hibernate 使用的访问类型将是字段或属性。EJB3 规范要求您在将被访问的元素类型上声明注释,即,如果您使用属性访问,则为 getter 方法,如果您使用字段访问,则为字段。应避免在字段和方法中混合使用 EJB3 注释。Hibernate 会从@Id 或@EmbeddedId 的位置猜测访问类型。

于 2008-11-20T23:05:26.810 回答
12

你让我走上了正确的轨道工具包。谢谢。这是交易......当然,我人为的例子并没有包括整个故事。我的 Widget 类实际上比我给出的示例大得多。我有几个额外的字段/吸气剂,我正在混合我的注释。所以我在字段上注释了@Id,但其他人在getter上被注释了。

所以这个故事的寓意是你不能混合注释位置。所有注释都在字段上,或者它们在 getter 方法上。长期使用 Java 和 Hibernate,是 Annotations 的新手。每天学习一些东西。

一旦我知道谷歌需要什么,我就会发现这很有帮助 - http://chstath.blogspot.com/2007/05/field-access-vs-property-access-in-jpa.html

当然,这现在提出了一个问题,即从设计和性能的角度来看哪个更好。

于 2008-11-20T17:49:16.353 回答
1

一个很长的范围,但是你有一个旧*.hbm.xml文件吗?

也许它可能会选择错误的设置default-access并使用property而不是field

于 2008-11-20T17:20:25.070 回答
1

这是一个非常好的链接,可以帮助您了解访问类型和相关的最佳实践!

在 Hibernate 中理解@AccessType

于 2010-04-27T17:29:52.047 回答
0

如果您执行以下操作,它是否有效:

@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;}
}
于 2008-11-20T16:26:22.950 回答