是否可以拥有不可变的 JPA 实体?
在我们的 Hibernate 项目中,实体是使用 Java bean 模式进行编码的。我们的代码中有很多地方有人忘记设置赋值器,并且由于 NOT NULL
约束而导致异常。
是否有人使用构建器来构建他们的实体或使它们不可变?
我正在尝试找到一种不属于 Java bean 模式风格的有效模式。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果你让你的bean不可变,那么你必须使用字段级访问,这会带来一系列问题,正如彻底讨论的此处。我们采取的方法是让构建器/工厂为我们执行/验证需求等规则。
If you make your beans immutable then you have to use field level access and this comes with its own set of problems as discussed thoroughly here. The approach we took is to have a Builder/Factory enforcing/validating the requiredness etc rules for us.
在我们的项目中,我们确实使用普通构建器方法(@see effective Java)。考虑以下示例:
如果您有时想要改变实体,我建议引入
new Builder(Person person)
它将把所有数据复制回来,这样您就可以使用 builder 来改变它。当然,它会产生新的实体,因此旧的实体仍然是只读的。用法(带有突变)非常简单:
另外,值得注意的是,在这个例子中,Person 不是 100% 不可变(也不可能是)类:首先,因为 id 将是由 jpa 设置,也可以在运行时获取惰性关联,最后因为您不能拥有最终字段(由于需要默认构造函数):( 后一点也是多线程环境的一个问题,即实体可能传递给#build() 之后的另一个线程可能会导致各种错误,因为另一个线程不能保证看到完全构造的对象
JPA 2.1 规范的“2.1 实体类”部分说:
另一种类似的方法: http://vlkan.com/blog/post /2015/03/21/immutable-persistence/
在我的例子中,我只是将 id 添加到构建器,而不是在草稿之上构建服务。
In our project we do use vanilla builders approach (@see Effective Java). Consider the following example:
In case you want to sometimes mutate the entity I would recomend to introduce
new Builder(Person person)
which will copy all the data back, so you can mutate it with builder. Of course it will produce new one entity, so the old one remains read only.The usage (with mutation) is as simple as:
Also it is important to note that in this example Person is not 100% immutable (and can't be) class: first of all because id will be set by jpa, also lazy associations may be fetched at runtime and lastly because you can't have fields final(due to required default constructor) :( The latter point is also a concern for multithreaded environments, i.e. it is possible that entity passed to another thread just after #build() may lead to all kind of errors as abother thread is not guaranteed to see fully constructed object.
The JPA 2.1 specification, section "2.1 The Entity Class", says:
One more similar approach: http://vlkan.com/blog/post/2015/03/21/immutable-persistence/
In my case I would just add id to the builder instead building service on top of drafts..
@Immutable
注解可以用在Entity上。 JPA 将忽略对实体所做的所有更新。https://docs.jboss.org/ hibernate/orm/5.2/javadocs/org/hibernate/annotations/Immutable.html
@Immutable
annotation can be used on Entity. JPA Will ignore all updates made to entity.https://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/annotations/Immutable.html