java 在 Hibernate/JPA 中是否可以有不可变的字段?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7941161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to have immutable fields in Hibernate/JPA?
提问by Carlos
In our application, we need to have fields that are assignable only once.
在我们的应用程序中,我们需要有只能分配一次的字段。
At first we thought of encapsulating the fields and making the setters private. However, some questions arouse:
起初,我们想到了封装字段并使 setter 私有。但是,也引起了一些问题:
- Without a public setter, is Hibernate still able to map the field from the database?
- Can I strip out the setter and make the field mutable only in the entity constructor?
- Finally, is there any standard JPA way to make a field immutable?
- 如果没有公共设置器,Hibernate 是否仍然能够从数据库映射字段?
- 我可以去掉 setter 并使字段仅在实体构造函数中可变吗?
- 最后,是否有任何标准的 JPA 方法可以使字段不可变?
Thanks in advance.
提前致谢。
采纳答案by Tomasz Nurkiewicz
Ad. 1: I believe JPA uses plain private fields for both read and write if annotations are placed on fields and not on getters. Recently I discovered that Hibernate as an underlying JPA provider does not even need
get*()
andset*()
methods at all. This was truly enlightening solution since from the beginning I thought Hibernate needs accessors. So the answer is: you don't need settersas far as Hibernate is concerned.Ad. 2: However please note that Hibernate still needs no-arg constructor, otherwise it will fail to load entities with a descriptive exception. This is also a JPA requirement.
Ad. 3: No, there isn't. Remember that your collections would also had to be immutable.
广告。1:如果注释放在字段上而不是在 getter 上,我相信 JPA 使用普通的私有字段进行读取和写入。最近我发现 Hibernate 作为底层 JPA 提供者甚至根本不需要
get*()
和set*()
方法。这是真正有启发性的解决方案,因为从一开始我就认为 Hibernate 需要访问器。所以答案是:就 Hibernate 而言,您不需要 setter。广告。2:但是请注意,Hibernate 仍然需要无参数构造函数,否则它将无法加载具有描述性异常的实体。这也是 JPA 的要求。
广告。3:不,没有。请记住,您的集合也必须是不可变的。
回答by KaiThomasWerther
Try
尝试
@Column(updatable = false)
And make your setter private. (Leave your getter public if you want)
并将您的二传手设为私有。(如果需要,请公开您的吸气剂)
I think this is the best practice.
我认为这是最好的做法。
P.S.: JPA uses field access if you annotate your fields and uses getter/setter access if you annotate your getter method.
PS:如果您对字段进行注释,则 JPA 使用字段访问,如果您对 getter 方法进行注释,则使用 getter/setter 访问。
回答by Piotr Nowicki
In JPA 2.0 you have two ways to define what attributes should be persisted:
在 JPA 2.0 中,您有两种方法来定义应该保留哪些属性:
- Access(FIELD) - the fields name are persisted,
- Access(PROPERTY) - the properties name are persisted.
- Access(FIELD) - 字段名称被保留,
- Access(PROPERTY) - 属性名称被保留。
If no Access(-) annotation is used, the decision what access will be used depends on where you put your @Id annotation. If you put it next to your field - Access(FIELD) will be used. If you put it next to your accessor - Access(PROPERTY) will be used.
如果未使用 Access(-) 批注,则将使用何种访问权限的决定取决于您放置 @Id 批注的位置。如果您将它放在您的字段旁边 - 将使用 Access(FIELD)。如果您将它放在访问器旁边 - 将使用 Access(PROPERTY)。
Therefore, if you use Access(FIELD) you don't have to have an appropriate JavaBeans-style accessor for particular field. You can have a private field named 'myField' and a public setter for it named 'public setBlahBlah(-)'. The JPA will persist just the 'myField'.
因此,如果您使用 Access(FIELD),则不必为特定字段使用合适的 JavaBeans 样式访问器。您可以拥有一个名为“myField”的私有字段和一个名为“public setBlahBlah(-)”的公共设置器。JPA 将只保留“myField”。
回答by bbviana
Try
尝试
@Column(updatable = false)
From javadoc:
来自 javadoc:
Whether the column is included in SQL UPDATE statements generated by the persistence provider.
该列是否包含在持久性提供程序生成的 SQL UPDATE 语句中。
回答by Desmond Zhou
You can mark an entity with @Entity(mutable=false)
or @Immutable
annotations for the framework to make use of this fact for performance gain in caching and such. (Hibernate)
您可以使用框架@Entity(mutable=false)
或@Immutable
注释标记实体,以利用这一事实来提高缓存等方面的性能。(休眠)
Then you can use an immutable wrapper class like this:
然后你可以像这样使用一个不可变的包装类:
public class ImmutableStuff {
private final FooField barValue;
public ImmutableStuff(Stuff stuff) {
barValue = stuff.barValue;
}
public FooField getBarValue(){
return barValue;
}
}