java Hibernate 注释放置问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/305880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 11:52:10  来源:igfitidea点击:

Hibernate Annotation Placement Question

javahibernateannotations

提问by SteveT

I've got what I think is a simple question. I've seen examples both ways. The question is - "why can't I place my annotations on the field?". Let me give you an example....

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

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

The above code works fine (assuming there's not a typo in there). When the annotation is placed on the getter of the property everything is perfect.

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

However, that seems awkward to me. In my mind it's cleaner to place the annotation on the field, like so --

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

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

I've seen examples of both ways. However, when I run this second example I get the following...

我见过两种方式的例子。但是,当我运行第二个示例时,我得到以下信息...

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
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;
}
0(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) ...

Here's the skeleton of HibernateSessionFactory(line 25 is marked) ....

这是HibernateSessionFactory(标记了第 25 行)的骨架....

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

Anyone have an idea what's going on here?

任何人都知道这里发生了什么?

回答by Varun Mehta

From a performance and design perspective, using annotations on getters is a better idea than member variables, because the getter setters are called using reflection if placed on the field, than a method. Also if you plan to use validation and other features of hibernate, you'll have all the annotations at one place, rather than scattering them all over the place.

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

My recommendation go with methods not member variables.

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

From the documentation

从文档

Depending on whether you annotate fields or methods, the access type used by Hibernate will be field or property. The EJB3 spec requires that you declare annotations on the element type that will be accessed, i.e. the getter method if you use property access, the field if you use field access. Mixing EJB3 annotations in both fields and methods should be avoided. Hibernate will guess the access type from the position of @Id or @EmbeddedId.

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

回答by SteveT

You got me on the right track toolkit. Thanks. Here's the deal... Of course, my contrived example didn't include the whole story. My Widget class was actually much larger than the example I gave. I have several extra fields/getters and I was MIXINGmy annotations. So I was annotating the @Id on the field but others were being annotated on the getter.

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

So the moral of the story is that you cannot mix annotation locations. Either all annotations are on the fields or they are on the getter methods. Long time Java and Hibernate, new to Annotations. Learn something every day.

所以这个故事的寓意是你不能混合注释位置。要么所有注释都在字段上,要么在 getter 方法上。很长一段时间 Java 和 Hibernate,新的注解。每天学点东西。

Once I knew what to Google for I came across this which was helpful - http://chstath.blogspot.com/2007/05/field-access-vs-property-access-in-jpa.html

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

Of course, this now brings up the question as to which is better from design and performance perspectives.

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

回答by toolkit

A long reach, but do you have an old *.hbm.xmlfile floating around?

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

Perhaps it might be picking up the wrong setting for default-accessand using propertyinstead of field?

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

回答by sundary

This is a very nice link that can help you with understanding the accesstypes and the relted best practices!

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

Understading @AccessType in Hibernate

了解Hibernate 中的 @AccessType

回答by Jonathan

Does it work if you do the following:

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

##代码##