为什么JPA有一个@Transient注解?

jogvjijk  于 2023-11-18  发布在  其他
关注(0)|答案(8)|浏览(168)

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

iecba09b

iecba09b1#

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

j91ykkif

j91ykkif2#

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

6yoyoihd

6yoyoihd3#

正如其他人所说,@Transient用于标记不应该持久化的字段。考虑这个简短的例子:

  1. public enum Gender { MALE, FEMALE, UNKNOWN }
  2. @Entity
  3. public Person {
  4. private Gender g;
  5. private long id;
  6. @Id
  7. @GeneratedValue(strategy=GenerationType.AUTO)
  8. public long getId() { return id; }
  9. public void setId(long id) { this.id = id; }
  10. public Gender getGender() { return g; }
  11. public void setGender(Gender g) { this.g = g; }
  12. @Transient
  13. public boolean isMale() {
  14. return Gender.MALE.equals(g);
  15. }
  16. @Transient
  17. public boolean isFemale() {
  18. return Gender.FEMALE.equals(g);
  19. }
  20. }

字符串
当这个类被提供给JPA时,它会持久化genderid,但不会尝试持久化helper boolean方法--如果没有@Transient,底层系统会抱怨Entity类Person缺少setMale()setFemale()方法,因此根本不会持久化Person

展开查看全部
91zkwejq

91zkwejq4#

目的不同:

transient关键字和@Transient注解有两个不同的用途:一个处理序列化,一个处理持久化。作为程序员,我们经常将这两个概念结合在一起,但这通常是不准确的。Persistence指的是状态的特征,它比创建它的进程存在得更久。Serialization在Java中指的是编码/将对象的状态解码为字节流。

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

如果字段使用transient关键字,则在对象转换为字节流时该字段将不会被序列化。此外,由于JPA将标记有transient关键字的字段视为具有@Transient注解,因此JPA也不会持久化该字段。
另一方面,当对象被序列化时,注解为@Transient的字段转换为字节流,但它不会被JPA持久化。因此,transient关键字是比@Transient注解更强的条件。

示例

这就引出了一个问题:为什么会有人想要序列化一个没有持久化到应用程序数据库的字段呢?事实上,序列化不仅仅用于持久化。在Enterprise Java应用程序中,需要 * 一种在分布式组件之间交换对象的机制 *;串行化提供了一个通用的通信协议来处理这个问题。因此,字段可以保存用于组件间通信的关键信息;但是从持久性的Angular 来看,同一字段可能没有价值。
例如,假设一个优化算法在服务器上运行,并且假设这个算法需要几个小时才能完成。对于客户端来说,拥有最新的解决方案集是很重要的。因此,客户端可以订阅服务器并在算法的执行阶段接收定期更新。这些更新是使用ProgressReport对象提供的:

  1. @Entity
  2. public class ProgressReport implements Serializable{
  3. private static final long serialVersionUID = 1L;
  4. @Transient
  5. long estimatedMinutesRemaining;
  6. String statusMessage;
  7. Solution currentBestSolution;
  8. }

字符串
Solution类可能看起来像这样:

  1. @Entity
  2. public class Solution implements Serializable{
  3. private static final long serialVersionUID = 1L;
  4. double[][] dataArray;
  5. Properties properties;
  6. }


服务器将每个ProgressReport持久化到它的数据库中。服务器不关心持久化estimatedMinutesRemaining,但客户端肯定关心这些信息。因此,estimatedMinutesRemaining使用@Transient进行注解。当算法找到最终的Solution时,它直接由JPA持久化,而不使用ProgressReport

展开查看全部
v7pvogib

v7pvogib5#

如果你只是想让一个字段不被持久化,那么transient和**@Transient都可以工作。但问题是为什么@Transient**,因为transient已经存在了。

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

假设你创建了一个实体,做了一些消耗CPU的计算得到了一个结果,这个结果不会保存在数据库中。但是你想把这个实体发送给其他Java应用程序供JMS使用,那么你应该使用@Transient,而不是JavaSE关键字transient。这样运行在其他VM上的接收者就可以保存他们重新计算的时间。

pprl5pva

pprl5pva6#

通俗地说,如果你在实体的属性上使用@Transient注解:这个属性将被单独挑出来,不会保存到数据库中。实体中对象的其余属性仍然会被保存。
x1c 0d1x的数据
我使用jpa存储库内置的保存方法将Object保存到数据库中,如下所示:

  1. userRoleJoinRepository.save(user2);

字符串

l2osamch

l2osamch7#

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

  1. import javax.persistence.Transient

字符串

cclgggtu

cclgggtu8#

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

相关问题