【问题标题】:Is it possible to have immutable fields in Hibernate/JPA?在 Hibernate/JPA 中是否可以有不可变的字段?
【发布时间】:2011-12-17 23:25:29
【问题描述】:

在我们的应用程序中,我们需要有只能分配一次的字段。

起初我们考虑封装字段并将设置器设为私有。但是,会引起一些问题:

  • 没有公共设置器,Hibernate 是否仍然能够映射数据库中的字段?
  • 我可以去掉 setter 并使字段只在实体构造函数中可变吗?
  • 最后,是否有任何标准的 JPA 方法可以使字段不可变?

提前致谢。

【问题讨论】:

    标签: java hibernate jpa-2.0 immutability


    【解决方案1】:

    在 JPA 2.0 中,您有两种方法来定义应该保留哪些属性:

    1. Access(FIELD) - 字段名称保持不变,
    2. Access(PROPERTY) - 属性名称保持不变。

    如果没有使用 Access(-) 批注,则决定使用何种访问权限取决于您将 @Id 批注放在哪里。如果你把它放在你的字段旁边 - 将使用 Access(FIELD)。如果您将它放在访问器旁边 - 将使用 Access(PROPERTY)。

    因此,如果您使用 Access(FIELD),则不必为特定字段使用适当的 JavaBeans 样式访问器。您可以有一个名为“myField”的私有字段和一个名为“public setBlahBlah(-)”的公共设置器。 JPA 将只保留“myField”。

    【讨论】:

      【解决方案2】:
      • 广告。 1:如果注释放在字段上而不是 getter 上,我相信 JPA 使用普通私有字段进行读取和写入。最近我发现 Hibernate 作为底层 JPA 提供者甚至根本不需要 get*()set*() 方法。这是真正有启发性的解决方案,因为从一开始我就认为 Hibernate 需要访问器。所以答案是:你不需要设置器就 Hibernate 而言。

      • 广告。 2:但是请注意,Hibernate 仍然需要无参数构造函数,否则它将无法加载实体并出现描述性异常。这也是 JPA 要求。

      • 广告。 3:不,没有。请记住,您的集合也必须是不可变的。

      【讨论】:

      • 所以,对于字段访问:private fields + Hibernate FIELD-access + no arg 构造函数(用于 Hibernate)+ arg 构造函数(用于制作不可变对象)?就这些了,@Tomasz?
      • 我只想补充一点,可以将无参数构造函数声明为private。因此,如果您有一个带有两个 final 字段的 Point 类:xy,您可以拥有一个供客户端代码使用的公共构造函数 Point(int x,int y) 和一个供客户端代码使用的私有构造函数 Point()冬眠。写一个注释来解释私有构造函数的目的是个好主意。
      • @W.K.S 更好的主意是创建自定义注释(例如@ForHibernate)。添加注释(至少是 Eclipse)后,您的 IDE 可能会停止将该构造函数标记为未使用
      【解决方案3】:

      您可以使用@Entity(mutable=false)@Immutable 注释为框架标记实体,以利用此事实在缓存等方面提高性能。 (休眠)

      然后你可以像这样使用不可变的包装类:

      public class ImmutableStuff {
          private final FooField barValue;
      
          public ImmutableStuff(Stuff stuff) {
              barValue = stuff.barValue;
          }
      
          public FooField getBarValue(){
              return barValue;
          }
      }
      

      【讨论】:

        【解决方案4】:

        试试

        @Column(updatable = false)
        

        并将您的二传手设为私有。 (如果你愿意,可以公开你的 getter)

        我认为这是最好的做法。

        P.S.:如果你注释你的字段,JPA 使用字段访问,如果你注释你的 getter 方法,则使用 getter/setter 访问。

        【讨论】:

        • 遗憾的是这是真的,但是尝试更新列只会忽略该字段,如果程序员忘记了该标志并假设它是可写的,则会导致可怕的错误。
        【解决方案5】:

        试试

        @Column(updatable = false)
        

        来自 javadoc:

        该列是否包含在由生成的 SQL UPDATE 语句中 持久性提供程序。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-01-28
          • 2012-01-15
          • 1970-01-01
          • 1970-01-01
          • 2020-07-13
          • 2011-04-06
          • 1970-01-01
          相关资源
          最近更新 更多