我实际上是在寻找一个“@Ignore”类型的注释,我可以用它来停止某个特定字段的持久化。如何实现这一目标?
当前回答
None of the above answers worked for me using Hibernate 5.2.10, Jersey 2.25.1 and Jackson 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 Jackson2 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:
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>
其他回答
根据实体属性类型,有多种解决方案。
基本属性
假设您有以下帐户表:
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表:
您希望将Post实体中的latestComment关联映射到添加的最新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
另一种忽略已经由实体标识符映射的关联的方法是使用@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忽略实体标识符属性,而使用关联。
使用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();
}
}
}
@JoinColumn注释的可插入和可更新属性将指示Hibernate忽略post关联,因为实体标识符负责处理post_id主键列。
@瞬态符合您的需求。
为了完成上面的回答,我使用了一个XML映射文件,其中@Transient和transient都不工作… 我必须把临时信息放在xml文件中:
<attributes>
(...)
<transient name="field" />
</attributes>
None of the above answers worked for me using Hibernate 5.2.10, Jersey 2.25.1 and Jackson 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 Jackson2 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:
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>
要忽略一个字段,请使用@Transient注释它,这样它就不会被hibernate映射。 来源:Hibernate注解。
推荐文章
- 在maven中安装mvn到底做什么
- 不可变与不可修改的集合
- 如何在JSON中使用杰克逊更改字段名
- GSON -日期格式
- 如何从线程捕获异常
- 无法解析主机"<URL here>"没有与主机名关联的地址
- 如何在Java中打印二叉树图?
- String.format()在Java中格式化双重格式
- com.jcraft.jsch.JSchException: UnknownHostKey
- Java中的操作符重载
- 如何加速gwt编译器?
- 在Hibernate中重新连接分离对象的正确方法是什么?
- 为什么我应该使用基于文档的数据库而不是关系数据库?
- 应该……接住环内还是环外?
- 哪个更快/最好?SELECT *或SELECT columnn1, colum2, column3等