Java 在持久化期间忽略 JPA 字段的最简单方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1281952/
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
What is the easiest way to ignore a JPA field during persistence?
提问by m2o
I'm essentially looking for a "@Ignore" type annotation with which I can stop a particular field from being persisted. How can this be achieved?
我本质上是在寻找一个“@Ignore”类型的注释,我可以用它来阻止特定的字段被持久化。如何做到这一点?
采纳答案by cletus
@Transient
complies with your needs.
@Transient
符合您的需求。
回答by Jonathan
To ignore a field, annotate it with @Transient
so it will not be mapped by hibernate.
Source: Hibernate Annotations.
要忽略字段,请对其进行注释,@Transient
使其不会被休眠映射。
来源:Hibernate 注释。
回答by Olimpiu POP
This answer comes a little late, but it completes the response.
这个答案来得有点晚,但它完成了响应。
In order to avoid a field from an entity to be persisted in DB one can use one of the two mechanisms:
为了避免实体中的字段在 DB 中持久化,可以使用以下两种机制之一:
@Transient- the JPA annotation marking a field as not persistable
@Transient- 将字段标记为不可持久化的 JPA 注释
transientkeyword in java. Beware - using this keyword, will prevent the field to be used with any serialization mechanism from java. So, if the field must be serialized you'd better use just the @Transientannotation.
java中的transient关键字。当心 - 使用此关键字将阻止该字段与来自 java 的任何序列化机制一起使用。因此,如果字段必须被序列化,您最好只使用@Transient注释。
回答by Vinze
To complete the above answers, I had the case using an XML mapping file where neither the @Transient
nor transient
worked...
I had to put the transient information in the xml file:
为了完成上述答案,我有一个使用 XML 映射文件的案例,其中既不工作@Transient
也不transient
工作......我不得不将瞬态信息放在 xml 文件中:
<attributes>
(...)
<transient name="field" />
</attributes>
回答by Kamil Nekanowicz
To ignore a field, annotate it with @Transient
so it will not be mapped by hibernate.
要忽略字段,请对其进行注释,@Transient
使其不会被休眠映射。
but then Hymanson will not serializethe field when converting to JSON.
但是当转换为 JSON 时,Hymanson 不会序列化该字段。
If you need mix JPA with JSON(omit by JPA but still include in Hymanson) use @JsonInclude
:
如果您需要将 JPA 与 JSON 混合使用(JPA 省略但仍包含在 Hymanson 中),请使用@JsonInclude
:
@JsonInclude()
@Transient
private String token;
TIP:
提示:
You can also use JsonInclude.Include.NON_NULLand hide fields in JSON during deserialization when token == null
:
在以下情况下,您还可以在反序列化期间使用JsonInclude.Include.NON_NULL并隐藏 JSON 中的字段token == null
:
@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
private String token;
回答by Hodglem
None of the above answers worked for me using Hibernate 5.2.10, Jersey 2.25.1 and Hymanson 2.8.9. I finally found the answer (sort of, they reference hibernate4module but it works for 5 too) here. None of the Json annotations worked at all with @Transient
. Apparently Hymanson2 is 'smart' enough to kindly ignore stuff marked with @Transient
unless you explicitly tell it not to. The key was to add the hibernate5 module (which I was using to deal with other Hibernate annotations) and disable the USE_TRANSIENT_ANNOTATION
feature in my Jersey Application:
使用 Hibernate 5.2.10、Jersey 2.25.1 和 Hymanson 2.8.9,上述答案都不适合我。我终于找到了答案(在某种程度上,它们引用hibernate4module但它工作在5太)在这里。没有任何 Json 注释与@Transient
. 显然,Hymanson2 足够“聪明”,可以忽略标有 的内容,@Transient
除非您明确告诉它不要。关键是添加 hibernate5 模块(我用来处理其他 Hibernate 注释)并USE_TRANSIENT_ANNOTATION
在我的 Jersey 应用程序中禁用该功能:
ObjectMapper HymansonObjectMapper = new ObjectMapper();
Hibernate5Module HymansonHibernateModule = new Hibernate5Module();
HymansonHibernateModule.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
HymansonObjectMapper.registerModule(HymansonHibernateModule);
Here is the dependency for the Hibernate5Module:
这是 Hibernate5Module 的依赖项:
<dependency>
<groupId>com.fasterxml.Hymanson.datatype</groupId>
<artifactId>Hymanson-datatype-hibernate5</artifactId>
<version>2.8.9</version>
</dependency>
回答by Vlad Mihalcea
There are multiple solutions depending on the entity attribute type.
根据实体属性类型,有多种解决方案。
Basic attributes
基本属性
Consider you have the following account
table:
考虑您有下account
表:
The account
table is mapped to the Account
entity like this:
该account
表被映射到这样的Account
实体:
@Entity(name = "Account")
public class Account {
@Id
private Long id;
@ManyToOne
private User owner;
private String iban;
private long cents;
private double interestRate;
private Timestamp createdOn;
@Transient
private double dollars;
@Transient
private long interestCents;
@Transient
private double interestDollars;
@PostLoad
private void postLoad() {
this.dollars = cents / 100D;
long months = createdOn.toLocalDateTime()
.until(LocalDateTime.now(), ChronoUnit.MONTHS);
double interestUnrounded = ( ( interestRate / 100D ) * cents * months ) / 12;
this.interestCents = BigDecimal.valueOf(interestUnrounded)
.setScale(0, BigDecimal.ROUND_HALF_EVEN).longValue();
this.interestDollars = interestCents / 100D;
}
//Getters and setters omitted for brevity
}
The basic entity attributes are mapped to table columns, so properties like id
, iban
, cents
are basic attributes.
基本实体属性映射到表列,因此属性喜欢id
,iban
,cents
是基本属性。
But the dollars
, interestCents
, and interestDollars
are computed properties, so you annotate them with @Transient
to exclude them from SELECT, INSERT, UPDATE, and DELETE SQL statements.
但是dollars
,interestCents
和interestDollars
计算性能,让您与注释他们@Transient
从SELECT,INSERT,UPDATE和DELETE SQL语句中排除。
So, for basic attributes, you need to use
@Transient
in order to exclude a given property from being persisted.For more details about computed entity attributes, check out this article.
因此,对于基本属性,您需要使用
@Transient
以从持久化中排除给定的属性。有关计算实体属性的更多详细信息,请查看这篇文章。
Associations
协会
Assuming you have the following post
and post_comment
tables:
假设您有以下post
和post_comment
表格:
You want to map the lastestComment
association in the Post
entity to the latest PostComment
entity that was added.
您希望lastestComment
将Post
实体中的关联映射到PostComment
添加的最新实体。
To do that, you can use the @JoinFormula
annotation:
为此,您可以使用@JoinFormula
注释:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
private Long id;
private String title;
@ManyToOne(fetch = FetchType.LAZY)
@JoinFormula("(" +
"SELECT pc.id " +
"FROM post_comment pc " +
"WHERE pc.post_id = id " +
"ORDER BY pc.created_on DESC " +
"LIMIT 1" +
")")
private PostComment latestComment;
//Getters and setters omitted for brevity
}
When fetching the Post
entity, you can see that the latestComment
is fetched, but if you want to modify it, the change is going to be ignored.
获取Post
实体时,可以看到latestComment
已获取,但如果要修改它,更改将被忽略。
So, for associations, you can use
@JoinFormula
to ignore the write operations while still allowing reading the association.For more details about computed associations, check out this article.
因此,对于关联,您可以使用
@JoinFormula
忽略写操作,同时仍然允许读取关联。有关计算关联的更多详细信息,请查看这篇文章。
@MapsId
@MapsId
Another way to ignore associations that are already mapped by the entity identifier is to use @MapsId
.
忽略已由实体标识符映射的关联的另一种方法是使用@MapsId
.
For instance, consider the following one-to-one table relationship:
例如,考虑以下一对一的表关系:
The PostDetails
entity is mapped like this:
在PostDetails
实体映射是这样的:
@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
}
Notice that both the id
attribute and the post
association map the same database column, which is the post_details
Primary Key column.
请注意,id
属性和post
关联都映射相同的数据库列,即post_details
主键列。
To exclude the id
attribute, the @MapsId
annotation will tell Hibernate that the post
association takes care of the table Primary Key column value.
为了排除该id
属性,@MapsId
注解会告诉 Hibernatepost
关联负责处理表的主键列值。
So, when the entity identifier and an association share the same column, you can use
@MapsId
to ignore the entity identifier attribute and use the association instead.For more details about
@MapsId
, check out this article.
因此,当实体标识符和关联共享同一列时,您可以使用
@MapsId
忽略实体标识符属性并使用关联来代替。有关更多详细信息
@MapsId
,请查看这篇文章。
Using insertable = false, updatable = false
使用 insertable = false, updatable = false
Another option is to use insertable = false, updatable = false
for the association which you want to be ignored by Hibernate.
另一种选择是insertable = false, updatable = false
用于您希望被 Hibernate 忽略的关联。
For instance, we can map the previous one-to-one association like this:
例如,我们可以像这样映射之前的一对一关联:
@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {
@Id
@Column(name = "post_id")
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne
@JoinColumn(name = "post_id", insertable = false, updatable = false)
private Post post;
//Getters and setters omitted for brevity
public void setPost(Post post) {
this.post = post;
if (post != null) {
this.id = post.getId();
}
}
}
The insertable
and updatable
attributes of the @JoinColumn
annotation will instruct Hibernate to ignore the post
association since the entity identifier takes care of the post_id
Primary Key column.
注释的insertable
和updatable
属性@JoinColumn
将指示 Hibernate 忽略post
关联,因为实体标识符负责post_id
主键列。
回答by Obothlale
Sometimes you want to:
有时你想:
- Serialize a column
- Ignore column from being persisted:
- 序列化一列
- 忽略被持久化的列:
Use @Column(name = "columnName", insertable = false, updatable = false)
用 @Column(name = "columnName", insertable = false, updatable = false)
A good scenario is when a certain column is automatically calculated by using other column values
一个很好的场景是当某个列使用其他列值自动计算时