Tại sao JPA có chú thích @Transient?


Câu trả lời:


455

transientTừ khóa của Java được sử dụng để biểu thị rằng một trường không được tuần tự hóa, trong khi @Transientchú thích của JPA được sử dụng để chỉ ra rằng một trường không được duy trì trong cơ sở dữ liệu, nghĩa là ngữ nghĩa của chúng là khác nhau.


3
Vâng, ngữ nghĩa là khác nhau. Nhưng tại sao JPA được thiết kế theo cách này?
Dilum Ranatunga

1
Không chắc là tôi hiểu bạn, nhưng hãy xem câu trả lời của "Pascal Thivent";)
Jawher

30
Điều này rất hữu ích vì bạn có thể không muốn lưu trữ dữ liệu trong cơ sở dữ liệu, nhưng bạn muốn lưu trữ nó trong hệ thống Chaching JPA sử dụng tuần tự hóa để lưu trữ / khôi phục các thực thể.
Kdeveloper

1
"Hệ thống bộ nhớ JPA" nào sử dụng tuần tự hóa để lưu trữ / khôi phục các thực thể? việc triển khai JPA có thể lưu trữ một đối tượng theo bất kỳ cách nào họ muốn và việc tuần tự hóa không tham gia vào đối tượng đó.
DataNucleus

@Jawher, ở đây đối với tạm thời không có nghĩa là không tồn tại bất kỳ giá trị nào hoặc nó sẽ chèn giá trị mặc định cho thuộc tính đó.
Satish Sharma

115

Bởi vì chúng có ý nghĩa khác nhau. Các @Transientchú thích cho các nhà cung cấp JPA không tồn tại bất kỳ (không transient) thuộc tính. Cái kia nói với khung tuần tự hóa để không tuần tự hóa một thuộc tính. Bạn có thể muốn có một @Transienttài sản và vẫn tuần tự hóa nó.


Cảm ơn câu trả lời Pascal. Như một ghi chú từ nhận xét của bạn: "Bạn có thể muốn có một thuộc tính @Transient và vẫn tuần tự hóa nó." (Đó là những gì tôi đang tìm kiếm) Tôi cũng muốn thêm rằng điều ngược lại là không đúng sự thật. Nếu người ta đặt một biến là nhất thời, thì bạn không thể duy trì nó.
jfajunior

96

Như những người khác đã nói, @Transientđược sử dụng để đánh dấu các trường không nên tồn tại. Xem xét ví dụ ngắn này:

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);
    }
}

Khi lớp này được cung cấp cho JPA, nó vẫn tồn tại genderidnhưng không cố gắng duy trì các phương thức boolean của trình trợ giúp - mà không có @Transienthệ thống cơ bản sẽ phàn nàn rằng lớp Entity Personbị thiếu setMale()setFemale()các phương thức và do đó sẽ không tồn Persontại.


@psp bạn có thể giải thích thêm về lý do tại sao / làm thế nào nó có thể gây ra hành vi không xác định? Cảm ơn!
taiduckman

@ 40Plot các đặc điểm kỹ thuật như vậy
psp

7
Đây phải là IMHO câu trả lời được chấp nhận vì nó giải thích nhiều hơn rằng câu trả lời hiện tại được chấp nhận ...
Honza Zidek

53

Mục đích là khác nhau:

Các transienttừ khóa và @Transientchú thích có hai mục đích khác nhau: một thỏa thuận với serialization và một thỏa thuận với sự kiên trì . Là lập trình viên, chúng tôi thường kết hợp hai khái niệm này thành một, nhưng nói chung điều này không chính xác. Sự kiên định đề cập đến đặc tính của trạng thái tồn tại lâu hơn quá trình tạo ra nó. Tuần tự hóa trong Java đề cập đến quá trình mã hóa / giải mã trạng thái của đối tượng dưới dạng luồng byte.

Các transienttừ khóa là một điều kiện mạnh hơn @Transient:

Nếu một trường sử dụng transienttừ khóa, trường đó sẽ không được tuần tự hóa khi đối tượng được chuyển đổi thành luồng byte. Hơn nữa, vì JPA coi các trường được đánh dấu bằng transienttừ khóa là có @Transientchú thích, nên trường cũng sẽ không được JPA duy trì.

Mặt khác, các trường được chú thích @Transientmột mình sẽ được chuyển đổi thành luồng byte khi đối tượng được tuần tự hóa, nhưng nó sẽ không được JPA duy trì. Do đó, transienttừ khóa là một điều kiện mạnh hơn @Transientchú thích.

Thí dụ

Điều này đặt ra câu hỏi: Tại sao mọi người muốn tuần tự hóa một trường không tồn tại trong cơ sở dữ liệu của ứng dụng? Thực tế là tuần tự hóa được sử dụng không chỉ là sự kiên trì . Trong một ứng dụng Java doanh nghiệp cần có một cơ chế để trao đổi các đối tượng giữa các thành phần phân tán ; serialization cung cấp một giao thức truyền thông chung để xử lý việc này. Do đó, một lĩnh vực có thể chứa thông tin quan trọng cho mục đích giao tiếp giữa các thành phần; nhưng cùng một lĩnh vực có thể không có giá trị từ quan điểm kiên trì.

Ví dụ: giả sử thuật toán tối ưu hóa được chạy trên máy chủ và giả sử thuật toán này mất vài giờ để hoàn thành. Đối với khách hàng, việc có một bộ giải pháp cập nhật nhất là rất quan trọng. Vì vậy, khách hàng có thể đăng ký vào máy chủ và nhận các bản cập nhật định kỳ trong giai đoạn thực hiện thuật toán. Những cập nhật này được cung cấp bằng cách sử dụng ProgressReportđối tượng:

@Entity
public class ProgressReport implements Serializable{

    private static final long serialVersionUID = 1L;

    @Transient
    long estimatedMinutesRemaining;
    String statusMessage;
    Solution currentBestSolution;

}

Các Solutionlớp có thể trông như thế này:

@Entity
public class Solution implements Serializable{

    private static final long serialVersionUID = 1L;

    double[][] dataArray;
    Properties properties;
}

Các máy chủ vẫn tồn tại mỗi ProgressReportcơ sở dữ liệu của nó. Máy chủ không quan tâm để tiếp tục estimatedMinutesRemaining, nhưng khách hàng chắc chắn quan tâm đến thông tin này. Do đó, estimatedMinutesRemainingđược chú thích bằng cách sử dụng @Transient. Khi trận chung kết Solutionđược định vị bằng thuật toán, nó được JPA duy trì trực tiếp mà không sử dụng a ProgressReport.


1
Nếu chúng thực sự là những mối quan tâm khác nhau, chắc chắn tồn tại một từ khác nắm bắt các sắc thái. Tại sao quá hạn? Như một gợi ý khởi đầu , @Unpersisted.
Dilum Ranatunga

4
Cá nhân tôi thích @Ephemeral. Theo Merriam Webster: Khi phù du lần đầu tiên được in bằng tiếng Anh vào những năm 1600, "đó là một thuật ngữ khoa học áp dụng cho các cơn sốt ngắn hạn, và sau đó, đối với các sinh vật (như côn trùng và hoa) với tuổi thọ rất ngắn. , nó có được một ý nghĩa mở rộng đề cập đến bất cứ điều gì thoáng qua và ngắn ngủi (như trong "thú vui phù du"). "
Austin D

1
Điều tôi cũng thích về câu trả lời này là nó đề cập rằng JPA coi transientcác lĩnh vực là hoàn toàn có @Transientchú thích. Vì vậy, nếu bạn sử dụng transienttừ khóa để ngăn chặn việc tuần tự hóa một trường thì nó cũng sẽ không kết thúc trong cơ sở dữ liệu.
neXus

17

Nếu bạn chỉ muốn một lĩnh vực sẽ không được duy trì, cả công việc tạm thời@Transient đều hoạt động. Nhưng câu hỏi là tại sao @Transient kể từ khi thoáng qua đã tồn tại.

Bởi vì trường @Transient vẫn sẽ được tuần tự hóa!

Giả sử bạn tạo một thực thể, thực hiện một số tính toán tiêu thụ CPU để có kết quả và kết quả này sẽ không lưu trong cơ sở dữ liệu. Nhưng bạn muốn gửi thực thể đến các ứng dụng Java khác để JMS sử dụng, thì bạn nên sử dụng @Transient, không phải từ khóa JavaSE transient. Vì vậy, các máy thu chạy trên các máy ảo khác có thể tiết kiệm thời gian của chúng để tính lại.


bạn có thể vui lòng cung cấp ví dụ để làm cho nó rõ ràng hơn?
Harsh Kanakhara

Có một chú thích rằng jpa sẽ coi là thoáng qua nhưng jackson sẽ không?
Kalpesh Soni

0

Tôi sẽ cố gắng trả lời câu hỏi "tại sao". Hãy tưởng tượng một tình huống trong đó bạn có một cơ sở dữ liệu khổng lồ với rất nhiều cột trong một bảng và dự án / hệ thống của bạn sử dụng các công cụ để tạo các thực thể từ cơ sở dữ liệu. (Hibernate có những thứ đó, v.v ...) Bây giờ, giả sử rằng theo logic kinh doanh của bạn, bạn cần một lĩnh vực cụ thể KHÔNG được tồn tại. Bạn phải "cấu hình" thực thể của mình theo một cách cụ thể. Mặc dù từ khóa Transient hoạt động trên một đối tượng - vì nó hoạt động trong ngôn ngữ java, nhưng @Transient chỉ được thiết kế để trả lời các tác vụ chỉ liên quan đến các tác vụ bền bỉ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.