Java 为什么 JPA 有 @Transient 注释?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2154622/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 04:11:56  来源:igfitidea点击:

Why does JPA have a @Transient annotation?

javajpajakarta-eeannotationstransient

提问by deamon

Java has the transientkeyword. Why does JPA have @Transientinstead of simply using the already existing java keyword?

Java 有transient关键字。为什么 JPA 有@Transient而不是简单地使用已经存在的 java 关键字?

采纳答案by Jawher

Java's transientkeyword is used to denote that a field is not to be serialized, whereas JPA's @Transientannotation is used to indicate that a field is not to be persisted in the database, i.e. their semantics are different.

Java的transient关键字用来表示一个字段不要序列化,而JPA的@Transient注解用来表示一个字段不要持久化到数据库中,即它们的语义不同。

回答by Pascal Thivent

Because they have different meanings. The @Transientannotation tells the JPA provider to not persist any (non-transient) attribute. The other tells the serialization framework to not serialize an attribute. You might want to have a @Transientproperty and still serialize it.

因为它们有不同的含义。该@Transient注解告诉JPA提供者不能坚持任何(非transient)属性。另一个告诉序列化框架不要序列化属性。您可能希望拥有一个@Transient属性并仍然对其进行序列化。

回答by Esko

As others have said, @Transientis used to mark fields which shouldn't be persisted. Consider this short example:

正如其他人所说,@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);
    }
}

When this class is fed to the JPA, it persists the genderand idbut doesn't try to persist the helper boolean methods - without @Transientthe underlying system would complain that the Entity class Personis missing setMale()and setFemale()methods and thus wouldn't persist Personat all.

当这个类被提供给 JPA 时,它会持久化genderid但不会尝试持久化辅助布尔方法 - 没有@Transient底层系统会抱怨Person缺少实体类setMale()setFemale()方法,因此根本不会持久化Person

回答by Sheng.W

If you just want a field won't get persisted, both transientand @Transientwork. But the question is why @Transientsince transientalready exists.

如果您只希望一个字段不会被持久化,那么transient@Transient 都可以工作。但问题是为什么@Transient因为瞬态已经存在。

Because @Transient field will still get serialized!

因为@Transient 字段仍然会被序列化!

Suppose you create a entity, doing some CPU-consuming calculation to get a result and this result will not save in database. But you want to sent the entity to other Java applications to use by JMS, then you should use @Transient, not the JavaSE keyword transient. So the receivers running on other VMs can save their time to re-calculate again.

假设您创建了一个实体,进行一些消耗 CPU 的计算以获得结果,并且该结果不会保存在数据库中。但是您想将实体发送给其他 Java 应用程序以供 JMS 使用,那么您应该使用@Transient,而不是 JavaSE 关键字transient。因此,在其他 VM 上运行的接收器可以节省再次重新计算的时间。

回答by Dima R.

I will try to answer the question of "why". Imagine a situation where you have a huge database with a lot of columns in a table, and your project/system uses tools to generate entities from database. (Hibernate has those, etc...) Now, suppose that by your business logic you need a particular field NOT to be persisted. You have to "configure" your entity in a particular way. While Transient keyword works on an object - as it behaves within a java language, the @Transient only designed to answer the tasks that pertains only to persistence tasks.

我将尝试回答“为什么”的问题。想象一下这样一种情况,你有一个巨大的数据库,表中有很多列,你的项目/系统使用工具从数据库生成实体。(Hibernate 有那些,等等......)现在,假设根据您的业务逻辑,您需要一个特定的字段不被持久化。您必须以特定方式“配置”您的实体。虽然 Transient 关键字作用于对象 - 因为它在 Java 语言中表现,@Transient 仅用于回答仅与持久性任务相关的任务。

回答by Austin D

Purpose is different:

目的不同:

The transientkeyword and @Transientannotation have two different purposes: one deals with serializationand one deals with persistence. As programmers, we often marry these two concepts into one, but this is not accurate in general. Persistencerefers to the characteristic of state that outlives the process that created it. Serializationin Java refers to the process of encoding/decoding an object's state as a byte stream.

transient关键字和@Transient注释有两个不同的目的:一个交易序列化,并与一个交易的持久性。作为程序员,我们经常将这两个概念合二为一,但这一般来说并不准确。持久性是指状态的特征,它比创建它的过程更持久。Java 中的序列化是指将对象状态编码/解码为字节流的过程。

The transientkeyword is a stronger condition than @Transient:

transient关键字是比更强的条件@Transient

If a field uses the transientkeyword, that field will not be serialized when the object is converted to a byte stream. Furthermore, since JPA treats fields marked with the transientkeyword as having the @Transientannotation, the field will not be persisted by JPA either.

如果某个字段使用了transient关键字,则在将对象转换为字节流时,该字段将不会被序列化。此外,由于 JPA 将标有transient关键字的字段视为具有@Transient注释,因此该字段也不会被 JPA 持久化。

On the other hand, fields annotated @Transientalone willbe converted to a byte stream when the object is serialized, but it will not be persisted by JPA. Therefore, the transientkeyword is a stronger condition than the @Transientannotation.

另一方面,@Transient单独注解的字段在对象序列化时转为字节流,但不会被JPA持久化。因此,transient关键字是比@Transient注释更强的条件。

Example

例子

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.

这就引出了一个问题:为什么有人想要序列化一个没有持久化到应用程序数据库的字段?现实情况是,序列化不仅仅用于持久性。在企业 Java 应用程序中,需要有一种机制来在分布式组件之间交换对象;序列化提供了一个通用的通信协议来处理这个问题。因此,一个字段可能包含用于组件间通信的关键信息;但从持久性的角度来看,同一个字段可能没有价值。

For example, suppose an optimization algorithm is run on a server, and suppose this algorithm takes several hours to complete. To a client, having the most up-to-date set of solutions is important. So, a client can subscribe to the server and receive periodic updates during the algorithm's execution phase. These updates are provided using the ProgressReportobject:

例如,假设优化算法在服务器上运行,并假设该算法需要几个小时才能完成。对于客户而言,拥有最新的解决方案集很重要。因此,客户端可以订阅服务器并在算法执行阶段接收定期更新。这些更新是使用ProgressReport对象提供的:

@Entity
public class ProgressReport implements Serializable{

    private static final long serialVersionUID = 1L;

    @Transient
    long estimatedMinutesRemaining;
    String statusMessage;
    Solution currentBestSolution;

}

The Solutionclass might look like this:

Solution类可能是这样的:

@Entity
public class Solution implements Serializable{

    private static final long serialVersionUID = 1L;

    double[][] dataArray;
    Properties properties;
}

The server persists each ProgressReportto its database. The server does not care to persist estimatedMinutesRemaining, but the client certainly cares about this information. Therefore, the estimatedMinutesRemainingis annotated using @Transient. When the final Solutionis located by the algorithm, it is persisted by JPA directly without using a ProgressReport.

服务器将每个持久化ProgressReport到其数据库。服务器不关心持久化estimatedMinutesRemaining,但客户端肯定关心这些信息。因此,estimatedMinutesRemaining使用@Transient. 当finalSolution被算法定位时,由JPA直接持久化,不使用ProgressReport.