Answers:
@Transient
符合您的需求。
要忽略某个字段,请用@Transient
对其进行注释,这样它就不会被休眠映射。
但是杰克逊在转换为JSON时不会序列化字段。
如果您需要将JPA与JSON混合使用(JPA省略但仍包含在Jackson中),请使用@JsonInclude
:
@JsonInclude()
@Transient
private String token;
小费:
您还可以使用JsonInclude.Include.NON_NULL并在反序列化期间在JSON时隐藏字段token == null
:
@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
private String token;
@JsonInclude
不需要该堆栈:@Transient
字段仍包含在JSON中。(您仍然得到我的投票:该技术本身在其他情况下可能非常有用)。
这个答案来得有点晚,但是它完成了回答。
为了避免实体中的字段保留在数据库中,可以使用以下两种机制之一:
@Transient -JPA注释将字段标记为不可持久
Java中的瞬时关键字。当心-使用此关键字,将阻止该字段与Java中的任何序列化机制一起使用。因此,如果必须对字段进行序列化,则最好仅使用 @Transient批注。
根据实体属性类型,有多种解决方案。
考虑您有下account
表:
该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
}
基本实体属性映射到表列,因此属性喜欢id
,iban
,cents
是基本属性。
但是dollars
,interestCents
和interestDollars
计算性能,让您与注释他们@Transient
从SELECT,INSERT,UPDATE和DELETE SQL语句中排除。
因此,对于基本属性,您需要使用
@Transient
以便将给定属性排除在外。有关计算实体属性的更多详细信息,请参阅本文。
假设你有以下post
和post_comment
表:
您想要lastestComment
将Post
实体中的关联映射到PostComment
已添加的最新实体。
为此,您可以使用@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
}
提取Post
实体时,您可以看到latestComment
已获取,但是如果要修改它,则更改将被忽略。
因此,对于关联,您可以使用
@JoinFormula
忽略写操作,同时仍然允许读取关联。有关计算关联的更多详细信息,请参阅本文。
忽略实体标识符已映射的关联的另一种方法是使用@MapsId
。
例如,考虑以下一对一表关系:
在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
}
请注意,id
属性和post
关联都映射同一数据库列,即“ post_details
主键”列。
为了排除该id
属性,@MapsId
注释将告诉Hibernate post
关联关系负责表的Primary Key列值。
因此,当实体标识符和关联共享同一列时,可以使用
@MapsId
忽略实体标识符属性,而使用关联。有关更多信息
@MapsId
,请查看本文。
insertable = false, updatable = false
另一种选择是insertable = false, updatable = false
用于要被Hibernate忽略的关联。
例如,我们可以像这样映射先前的一对一关联:
@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();
}
}
}
注释的insertable
和updatable
属性@JoinColumn
将指示Hibernate忽略post
关联,因为实体标识符负责“ post_id
主键”列。
post
和post_details
表为例,这是否正确?
使用Hibernate 5.2.10,Jersey 2.25.1和Jackson 2.8.9时,以上答案均不适用于我。我终于找到了答案(在某种程度上,它们引用hibernate4module但它工作在5太)在这里。没有Json注释与一起使用@Transient
。显然,Jackson2足够“聪明”,可以友好地忽略带有标记的内容,@Transient
除非您明确要求不要这样做。关键是添加hibernate5模块(我用来处理其他Hibernate批注)并USE_TRANSIENT_ANNOTATION
在Jersey应用程序中禁用该功能:
ObjectMapper jacksonObjectMapper = new ObjectMapper();
Hibernate5Module jacksonHibernateModule = new Hibernate5Module();
jacksonHibernateModule.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
jacksonObjectMapper.registerModule(jacksonHibernateModule);
这是Hibernate5Module的依赖项:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.8.9</version>
</dependency>
@JsonProperty
@JsonInclude
@JsonSerialize + @JsonDeserialize
mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, false));
此解决方案终于奏效。谢谢!