简体   繁体   中英

Why does JPA have a @Transient annotation?

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

Java的transient关键字用于表示一个字段不进行序列化,而JPA的@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.

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 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 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.

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 .

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.

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

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.

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.

例子:

Im saving the Object to the database using the jpa repository built in save method as so:

userRoleJoinRepository.save(user2);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM