transient
。为什么JPA不直接使用已经存在的Java关键字,而是使用@Transient
呢?transient
。为什么JPA不直接使用已经存在的Java关键字,而是使用@Transient
呢?Java中的transient
关键字用于表示某个字段不需要被序列化,而JPA中的@Transient
注解则表示某个字段不需要在数据库中持久化存储,也就是说它们的语义是不同的。
@Transient
注释告诉 JPA 提供程序不要持久化任何(非瞬态)属性。而另一个注释告诉序列化框架不要序列化属性。您可能希望拥有一个@Transient
属性,但仍要对其进行序列化。正如其他人所说,@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时,它会持久化gender
和id
,但不会尝试持久化辅助布尔方法 - 如果没有使用@Transient
注解,底层系统将抱怨实体类Person
缺少setMale()
和setFemale()
方法,因此根本不会持久化Person
。equals()
来比较枚举吗?这就像写 new Integer(3).equals(new Integer(3))
来比较数字一样。 - Jack目的不同:
transient
关键字和@Transient
注解有两个不同的目的:一个处理序列化,另一个处理持久化。作为程序员,我们经常将这两个概念合并成一个,但总体上这是不准确的。持久化指的是状态特征,它超出了创建它的进程的生命周期。Java中的序列化指的是将对象的状态编码/解码为字节流的过程。
transient
关键字比@Transient
注解更强:
如果一个字段使用了transient
关键字,在对象转换为字节流时,该字段将不会被序列化。此外,由于JPA将带有transient
关键字标记的字段视为具有@Transient
注解,因此该字段也不会被JPA持久化。
另一方面,仅带有@Transient
注解的字段将在对象序列化时转换为字节流,但不会被JPA持久化。因此,transient
关键字比@Transient
注解更强。
示例
这引出了一个问题:为什么有人想要序列化一个不被持久化到应用程序数据库的字段呢? 事实是,序列化用于更多的内容而不仅仅是持久化。在企业Java应用程序中,需要一种在分布式组件之间交换对象的机制;序列化提供了一个常见的通信协议来处理这个问题。因此,一个字段可能保存了用于组件间通信的关键信息;但是从持久性的角度来看,该字段可能没有价值。
例如,假设在服务器上运行了一个优化算法,并且假设该算法需要几个小时才能完成。对于客户端而言,拥有最新的解决方案集很重要。因此,客户端可以订阅服务器并在算法执行阶段定期接收更新。这些更新使用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
,但客户端肯定关心这些信息。因此,使用@Transient
对estimatedMinutesRemaining
进行了注释。当算法找到最终的Solution
时,JPA会直接将其持久化,而不使用ProgressReport
。@Unpersisted
。 - Dilum Ranatunga@Ephemeral
。根据韦氏词典:当“ephemeral”在17世纪首次印刷成英语时,“它是一个科学术语,用于短期发热,后来用于寿命非常短暂的生物(如昆虫和花卉)。不久之后,它获得了引申意义,指任何短暂而短暂的事物(如“ephemeral pleasures”)。” - Austintransient
字段视为隐含具有@Transient
注释。因此,如果您使用transient
关键字来防止字段序列化,则该字段也不会出现在数据库中。 - neXus如果你只希望某个字段不被持久化,使用transient和@Transient都可以。但是问题在于,既然已经有transient了,为什么还要使用@Transient?
因为@Transient字段仍会被序列化!
假设你创建了一个实体,在其中进行一些计算以获得结果,但是这个结果不会保存在数据库中。但是你想将该实体发送给其他使用JMS的Java应用程序,那么你应该使用@Transient
,而不是JavaSE关键字transient
。这样运行在其他VM上的接收者就可以节省时间,避免重新计算。
@Transient
是做什么用的?”,而是“为什么不使用关键字。” - E-Rizimport javax.persistence.Transient