Java有transient关键字。为什么JPA有@Transient而不是简单地使用已经存在的java关键字?
当前回答
正如其他人所说,@Transient用于标记不应该持久化的字段。请看这个简短的例子:
public enum Gender { MALE, FEMALE, UNKNOWN }
@Entity
public Person {
private Gender g;
private long id;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public Gender getGender() { return g; }
public void setGender(Gender g) { this.g = g; }
@Transient
public boolean isMale() {
return Gender.MALE.equals(g);
}
@Transient
public boolean isFemale() {
return Gender.FEMALE.equals(g);
}
}
当这个类被提供给JPA时,它持久化了性别和id,但不会尝试持久化helper布尔方法——如果没有@Transient,底层系统会抱怨实体类Person缺少setMale()和setFemale()方法,因此根本不会持久化Person。
其他回答
目的不同:
transient关键字和@Transient注释有两个不同的目的:一个处理序列化,一个处理持久性。作为程序员,我们经常把这两个概念结合在一起,但这通常是不准确的。持久性是指状态的特性,它比创造它的过程更持久。Java中的序列化是指将对象的状态编码/解码为字节流的过程。
关键字transient是一个比@Transient更强的条件:
如果字段使用了transient关键字,当对象转换为字节流时,该字段将不会被序列化。此外,由于JPA将标记有transient关键字的字段视为具有@Transient注释,因此JPA也不会持久化该字段。
另一方面,当对象被序列化时,单独带注释的@Transient字段将被转换为字节流,但JPA不会持久化它。因此,瞬态关键字是比@Transient注释更强的条件。
例子
This begs the question: Why would anyone want to serialize a field that is not persisted to the application's database? The reality is that serialization is used for more than just persistence. In an Enterprise Java application there needs to be a mechanism to exchange objects between distributed components; serialization provides a common communication protocol to handle this. Thus, a field may hold critical information for the purpose of inter-component communication; but that same field may have no value from a persistence perspective.
例如,假设在服务器上运行一个优化算法,并假设该算法需要几个小时才能完成。对于客户来说,拥有最新的解决方案集非常重要。因此,客户端可以订阅服务器,并在算法执行阶段定期接收更新。这些更新是使用ProgressReport对象提供的:
@Entity
public class ProgressReport implements Serializable{
private static final long serialVersionUID = 1L;
@Transient
long estimatedMinutesRemaining;
String statusMessage;
Solution currentBestSolution;
}
Solution类可能看起来像这样:
@Entity
public class Solution implements Serializable{
private static final long serialVersionUID = 1L;
double[][] dataArray;
Properties properties;
}
服务器将每个ProgressReport保存到它的数据库中。服务器并不关心如何持久化estimatedMinutesRemaining,但是客户端肯定关心这个信息。因此,estimatedMinutesRemaining使用@Transient进行注释。当最终的解决方案由算法定位时,它将由JPA直接持久化,而不使用ProgressReport。
正如其他人所说,@Transient用于标记不应该持久化的字段。请看这个简短的例子:
public enum Gender { MALE, FEMALE, UNKNOWN }
@Entity
public Person {
private Gender g;
private long id;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public Gender getGender() { return g; }
public void setGender(Gender g) { this.g = g; }
@Transient
public boolean isMale() {
return Gender.MALE.equals(g);
}
@Transient
public boolean isFemale() {
return Gender.FEMALE.equals(g);
}
}
当这个类被提供给JPA时,它持久化了性别和id,但不会尝试持久化helper布尔方法——如果没有@Transient,底层系统会抱怨实体类Person缺少setMale()和setFemale()方法,因此根本不会持久化Person。
因为它们有不同的含义。@Transient注释告诉JPA提供者不要持久化任何(非瞬态的)属性。另一个告诉序列化框架不要序列化某个属性。您可能希望有一个@Transient属性并仍然序列化它。
Java的transient关键字用于表示字段不被序列化,而JPA的@Transient注释用于表示字段不被持久化到数据库中,也就是说,它们的语义是不同的。
通俗地说,如果在实体的属性上使用@Transient注释:该属性将被单独挑选出来,不会保存到数据库中。实体内对象的其余属性仍将被保存。
我保存对象到数据库使用jpa存储库内置的保存方法,这样:
userRoleJoinRepository.save(user2);
推荐文章
- Java 8接口方法中不允许“同步”的原因是什么?
- 如何找到Java堆大小和内存使用(Linux)?
- Spring引导——不是托管类型
- 使用Enum实现单例(Java)
- RabbitMQ与通道和连接之间的关系
- buildSessionFactory()配置方法在Hibernate中已弃用?
- Spring MVC -如何获得所有的请求参数在一个地图在Spring控制器?
- 如何在Java中按两个字段排序?
- 文件之间的差异。路径中的分隔符和斜杠
- 在方法参数中使用NotNull注释
- Spring MVC中处理可选参数的@RequestParam
- Tomcat:如何查找正在运行的Tomcat版本?
- “java”、“javaw”和“javaws”之间有什么区别?
- 将Date对象转换为日历对象
- 在Java中保存最后N个元素的大小有限的队列