为什么JPA有@Transient注解?

发布于 2024-08-19 15:32:45 字数 99 浏览 4 评论 0原文

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

Java has the transient keyword. Why does JPA have @Transient instead of simply using the already existing java keyword?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

萤火眠眠 2024-08-26 15:32:45

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

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

不美如何 2024-08-26 15:32:45

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

Because they have different meanings. The @Transient annotation 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 @Transient property and still serialize it.

嗫嚅 2024-08-26 15:32:45

正如其他人所说,@Transient 用于标记不应保留的字段。考虑这个简短的示例:

public enum Gender { MALE, FEMALE, UNKNOWN }

@Entity
public class 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 == g;
    }

    @Transient
    public boolean isFemale() {
        return Gender.FEMALE == g;
    }
}

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

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

public enum Gender { MALE, FEMALE, UNKNOWN }

@Entity
public class 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 == g;
    }

    @Transient
    public boolean isFemale() {
        return Gender.FEMALE == g;
    }
}

When this class is fed to the JPA, it persists the gender and id but doesn't try to persist the helper boolean methods - without @Transient the underlying system would complain that the Entity class Person is missing setMale() and setFemale() methods and thus wouldn't persist Person at all.

玉环 2024-08-26 15:32:45

用途不同

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,但客户端当然关心这个信息。因此,estimatedMinutesRemaining 使用@Transient 进行注释。当算法找到最终的Solution时,它会直接由JPA持久化,而不使用ProgressReport

Purpose is different:

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

The transient keyword is a stronger condition than @Transient:

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

On the other hand, fields annotated @Transient alone will be converted to a byte stream when the object is serialized, but it will not be persisted by JPA. Therefore, the transient keyword is a stronger condition than the @Transient annotation.

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.

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 ProgressReport object:

@Entity
public class ProgressReport implements Serializable{

    private static final long serialVersionUID = 1L;

    @Transient
    long estimatedMinutesRemaining;
    String statusMessage;
    Solution currentBestSolution;

}

The Solution class might look like this:

@Entity
public class Solution implements Serializable{

    private static final long serialVersionUID = 1L;

    double[][] dataArray;
    Properties properties;
}

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

爱的十字路口 2024-08-26 15:32:45

如果您只是希望字段不被持久化,transient@Transient 都可以。但问题是为什么@Transient既然transient已经存在了。

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

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

If you just want a field won't get persisted, both transient and @Transient work. But the question is why @Transient since transient already exists.

Because @Transient field will still get serialized!

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.

我的奇迹 2024-08-26 15:32:45

通俗地说,如果对实体的某个属性使用@Transient注解:这个属性会被单挑出来,不会保存到数据库中。实体内对象的其余属性仍将被保存。

示例:

我使用 jpa 存储库内置的 save 方法将对象保存到数据库,如下所示:

userRoleJoinRepository.save(user2);

In laymen's terms, if you use the @Transient annotation on an attribute of an entity: this attribute will be singled out and will not be saved to the database. The rest of the attributes of the object within the entity will still be saved.

example:

I'm saving the Object to the database using the jpa repository built-in save method as so:

userRoleJoinRepository.save(user2);
风轻花落早 2024-08-26 15:32:45

对于 Kotlin 开发人员,请记住 Java transient 关键字将成为内置的 Kotlin @Transient 注释。因此,如果您在实体中使用 JPA @Transient,请确保您具有 JPA 导入:

import javax.persistence.Transient

For Kotlin developers, remember the Java transient keyword becomes the built-in Kotlin @Transient annotation. Therefore, make sure you have the JPA import if you're using JPA @Transient in your entity:

import javax.persistence.Transient
您的好友蓝忘机已上羡 2024-08-26 15:32:45

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文