【问题标题】:Does Hibernate always need a setter when there is a getter?当有 getter 时,Hibernate 是否总是需要一个 setter?
【发布时间】:2011-02-10 05:25:22
【问题描述】:

我们有一些使用@Column@Basic 注释的Hibernate getter 方法。

如果我们没有相应的设置器,我们会得到一个异常。为什么是这样?

在我们的例子中,我们派生从 getter 返回的值(以存储在 DB 中),而 setter 没有任何功能用途。所以我们只有一个空方法来绕过错误情况..

【问题讨论】:

  • 只是自动生成模型对象。 Eclipse、Dali 和/或 Hibernatetools 只需单击几下即可完成此操作。无需花费数小时编写 getter/setter,也无需担心其正确性和存在性。

标签: java hibernate getter-setter


【解决方案1】:

Hibernate 使用set 方法来初始化您从数据库中读取的实体。

也许,如果您对实体字段 defaultprotectedpublic 进行访问修饰符,那么 Hibernate 将直接初始化字段而不使用 setter(我读过一些关于它的内容,但我不确定它是否有效)。但是使用 setter 是更受欢迎的方式。

【讨论】:

  • 问题是我们只是将数据写入数据库,从不读取.. 但我猜 Hibernate 不知道这一点;)
  • 不幸的是,“private”修饰符不会强制 Hibernate 使用 setter :(
【解决方案2】:

您应该使用@Entity(access = AccessType.FIELD) 注释您的类并注释您的属性。这应该可以解决您的问题。 setter 是支持重构的最佳方式。那里有小二传手有什么问题。

【讨论】:

  • 只需将注释放在属性而不是 getter 上,它也应该可以正常工作(阅读关于访问类型的注释文档)。
  • 请记住,将访问类型从属性更改为字段可能会产生副作用。 Hibernate 将不再使用 getter 和 setter,而是直接通过反射访问字段,这意味着如果您的 getter 和 setter 中有任何特殊逻辑,它将不再被调用。
  • 我觉得他们甚至不应该实现特殊逻辑;)
  • 它显示了一个错误。看起来@Entity 没有任何参数名称访问权限。
  • @Saif 在这篇文章中没有提到 javax.persistence.Entity,而是 org.hibernate.annotations.Entity。但是在 4.1 版本的 Hibernate 之后它被弃用了,所以你可以给我们@javax.persistence.Access(javax.persistence.AccessType.FIELD)
【解决方案3】:

如果您不使用 setter 并使用私有属性,Hibernate 将不得不通过反射检索字段并执行 field.setAccessible(true)。我不认为 Hibernate 会这样做。

我真的不知道我们是否可以告诉 Hibernate 这样做,但据我记得,默认配置是使用 setter... 将 log/sysout 放在 set 上,您会看到它使用二传手。

【讨论】:

  • -1 因为如果字段或属性是私有的,Hibernate 就会这样做(使用 field.setAccessible(true))。
  • 实际上,我很确定在使用具有所有私有属性的 JPA / 实体 bean 时,休眠(我认为是 3.4)正在使用 setter ......但也许如果没有 setter 它会这样做。 ..不知道...
【解决方案4】:

正如其他人所提到的,如果您对属性 getter 方法进行注释,那么 Hibernate 在从数据库中读取值时会使用该 setter。基本上,Hibernate 假定它写入数据库的任何内容最终都需要从数据库中读取。这意味着如果您注解了一个 getter,那么它在从数据库中读取对象时需要调用一个 setter。

您可以将 setter 设为私有(Hibernate 将使用反射来访问 setter)。这是在保持类契约的同时仍然使用 Hibernate 进行关系映射的好方法。

如果该字段是从类中的其他属性派生的,那么为什么要将它存储在数据库中?您可以使用@Transient 注释来标记不应存储在数据库中的字段。您甚至可以使用 @Formula 注释让 Hibernate 为您派生字段(它通过使用发送到数据库的查询中的公式来完成此操作)。

【讨论】:

  • @Transient 在 getter 上的注解就足够了
【解决方案5】:

如果您不想使用 setter,请设置 access="field"

<class name="com.demo.hibernate.Country" table="country">
  <id name="countryId" column="id" type="int">
    <generator class="increment" />
  </id>
  <property name="name" column="name" access="field" type="string" />
  <property name="countryCode" column="country_code" access="field" type="string" />
</class>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-21
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多