Hibernate设置的字段可以是final吗?

3

当我保存Java文件时,我的Eclipse会自动执行一些代码清理操作,其中包括在可能的情况下向private字段添加final

这会与Hibernate将实体属性注入私有字段的能力发生冲突吗?

@Id
private final Long id = null;   // Eclipse made this "final"
                                // but Hibernate needs to set the id

我应该关闭这个保存操作吗?

更新:我已经测试了应用程序,并使用调试器查看了它,Hibernate确实重置了“final”字段,因此事情继续正常运行。但是这能够保证工作吗?例如,没有VM或编译器优化依赖于字段真正是最终的。那些可能会破坏。另一方面,通过反射设置private字段似乎是一种受支持的场景,因此相同的思路可能也适用于final


所以我想问的真正问题是:“如果我使用反射为私有final字段分配新值,那么我是否有破坏某些东西的风险?” - Thilo
我的Eclipse不应该这样做。 - Behrang
您可以配置Eclipse清理来执行此操作或不执行此操作:首选项\Java\代码样式\清理-编辑-选项卡“代码样式”中的“变量声明”... - Ralph
2个回答

1

即使它能工作,也不要这样做。

最终字段只能被写入一次,并且Java内存模型的某些部分基于此事实。

我发现了这篇博客http://www.polygenelubricants.com/2010/03/modifying-static-final-fields-through.html,它展示了如何通过反射使用真正的Hack来设置final。(但请不要在任何真实的应用程序中这样做。)

还有这个相关问题的答案:Is there any way to declare final fields for Hibernate-managed objects?

在您的情况下,最简单的解决方案是:将字段设置为可变的,并仅提供getter而不是setter。


0

嗯,有趣的问题。我认为在持久化对象上,您可能不想自动设置final,正如您提到的原因一样。

如果您的类具有某种功能,例如执行以下操作,则肯定会出现问题

setProperty(int prop) {
    this.prop = prop;
    fireChanged(); // updates other fields that depend on this one
}

这是我在专业环境中见过的。尽管在这里,插件可能足够聪明,不会将其变成最终版本。

如果您想使您的对象不可变,您可以让持久类返回一个不可变的子类,其中字段是私有的...

因此,使用该插件有优点和缺点。我想你可以任选一种方式,只要你进行测试以验证自动生成的最终版本不会妨碍程序流程。但个人而言,我不会使用该插件 -- 我会查看IDE警告并选择我的最终版本...


Hibernate似乎对final和private一样不太在意了... - Thilo
也许在这里,插件足够智能,不会使其变为final。它非常智能,并且随Eclipse一起提供,并列在推荐的代码清理列表中。因此,我真的很想保持它启用状态。 - Thilo
@thilo -- 在Hibernate中的字段级别访问使用反射,因此它可能可以绕过final关键字。我敢打赌这就是它能够正常工作的原因... - hvgotcodes
我只是想知道它是否真的有效。例如,最终字段似乎由内存模型以不同的方式处理,可能取决于它们是否是最终的。 - Thilo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接