Hibernate 注释放置问题

Posted

技术标签:

【中文标题】Hibernate 注释放置问题【英文标题】:Hibernate Annotation Placement Question 【发布时间】:2010-09-23 06:46:36 【问题描述】:

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

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

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

【问题讨论】:

也许你在第 22 行的 catch 块中吞下了一个异常? 【参考方案1】:

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

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

来自文档

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

【讨论】:

回复:because the getter setters are called using reflection,慢了多少?您是否粗略估计使用反射而不是字段的 getter 和 setter 需要多长时间?谢谢 我投了反对票,因为您没有回答为什么字段访问在 OP 的示例中不起作用。此外,您声称存在速度差异,但没有进行测试。 AFAIK,无论您注释字段还是方法,休眠都使用反射。另请参阅:***.com/questions/332591 @Navin +1 ***.com/questions/332591 表示性能没有显着差异。【参考方案2】:

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

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

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

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

【讨论】:

【参考方案3】:

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

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

【讨论】:

【参考方案4】:

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

了解@AccessType in Hibernate

【讨论】:

这个问题有点老了,但这里有一个新链接,提供了一些有价值的相关信息 - dzone.com/links/r/…【参考方案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;

【讨论】:

不。如果“按以下”表示@GeneratedValue 之后的空行。结果相同。 (感谢您的快速回复!)。 没问题。我原以为如果您以编程方式配置 Hibernate,那么您需要告诉 AnnotationConfiguration 在哪里可以找到带注释的类。请参阅以下内容:hibernate.org/hib_docs/annotations/reference/en/html_single/…

以上是关于Hibernate 注释放置问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 hibernate、hibernate 注释和 ehcache 的 Maven 依赖项是啥?

Hibernate 注释或 XML 配置

Hibernate @Where 注释语法问题

带有注释的 Spring + Hibernate:没有 Hibernate Session 绑定到线程

使用 Hibernate 注释映射 PostgreSQL 串行类型

Hibernate 默认模式和表注释