Чому JPA має анотацію @Transient?


283

Java має transientключове слово. Чому JPA @Transientзамість того, щоб просто використовувати вже існуюче ключове слово java?

Відповіді:


455

transientКлючове слово Java використовується для позначення того, що поле не підлягає серіалізації, тоді як @Transientанотація JPA використовується для вказівки на те, що поле не слід зберігати в базі даних, тобто їх семантика відрізняється.


3
Так, семантика різна. Але чому JPA була розроблена саме так?
— Dilum Ranatunga

1
Не впевнений, що я вас розумію, але подивіться на відповідь "Паскаля Тивента";)
— Jawher

30
Це зручно, оскільки ви, можливо, не хочете зберігати дані в базі даних, але ви хочете зберігати їх у системі Chaching JPA, яка використовує серіалізацію для зберігання / відновлення об'єктів.
— Kdeveloper

1
Що таке "система кешування JPA", яка використовує серіалізацію для зберігання / відновлення об'єктів? реалізація JPA може кешувати об'єкт будь-яким бажаним способом, а серіалізація не входить до нього.
— DataNucleus

@Jawher, тут для перехідних непресистентних значень не можна натискати жодне значення, інакше для цього атрибута буде вставлено значення за замовчуванням.
— Satish Sharma

115

Тому що вони мають різні значення. @TransientАнотацій повідомляє постачальник JPA не зберігаються яким - або (не- transient) атрибута. Інший говорить про рамки серіалізації, щоб не серіалізувати атрибут. Можливо, ви хочете мати @Transientвластивість і все ще його серіалізувати.


Дякую за відповідь Паскаль. Як зауваження до вашого коментаря: "Можливо, ви хочете мати властивість @Transient і все одно його серіалізувати." (Це було те, що я шукав) Я також хочу додати, що навпаки не вірно. Якщо встановити змінну як перехідну, ви не можете її зберегти.
— jfajunior

96

Як уже говорили інші, @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);
    }
}

Коли цей клас подається в JPA, він зберігається genderі idне намагається зберегти допоміжні булеві методи - без @Transientбазової системи скаржиться, що клас Entity Personвідсутній setMale()і setFemale()методи, і, таким чином, взагалі не існуватиме Person.


@psp Ви можете пояснити більше, чому / як це може спричинити невказану поведінку? Дякую!
— taiduckman

@ 40 Розмістіть специфікацію так
— psp

7
Це має бути IMHO прийнятою відповіддю, оскільки це набагато більше пояснює, що нинішній прийнятий ...
— Honza Zidek

53

Призначення інше:

transientКлючові слова та @Transientанотації мають дві різних цілей: один угоду з сериализацией і один угоду з збереженням . Як програмісти, ми часто поєднуємо ці два поняття в одне, але це взагалі не точно. Наполегливість позначається на характеристиці стану, що переживає процес, що його створив. Серіалізація в Java відноситься до процесу кодування / декодування стану об'єкта як потоку байтів.

transientКлючове слово є більш сильним , ніж умова @Transient:

Якщо в полі використовується transientключове слово, це поле не буде серіалізуватися при перетворенні об'єкта в потік байтів. Крім того, оскільки JPA розглядає поля, позначені transientключовим словом, як такі, що мають@Transient анотацію, поле JPA також не зберігатиметься.

З іншого боку, поля, позначені @Transientокремо, будуть перетворені в потік байтів, коли об'єкт серіалізується, але JPA не буде зберігатися. Тому transientключове слово є сильнішою умовою, ніж @Transientанотація.

Приклад

Це ставить питання: Чому хтось хотів би серіалізувати поле, яке не зберігається до бази даних програми? Реальність така, що серіалізація використовується більше, ніж просто наполегливість . У додатку Enterprise 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, не використовуючи a ProgressReport.


1
Якщо вони насправді викликають різні проблеми, напевно існує інше слово, яке фіксує нюанси. Навіщо перевантажувати цей термін? В якості стартера навіювання @Unpersisted.
— Dilum Ranatunga

4
Мені особисто подобається @Ephemeral. За словами Мерріам Вебстер: Коли ефемер вперше був надрукований англійською мовою в 1600-х роках, "це був науковий термін, застосований до короткочасних лихоманків, а пізніше - до організмів (таких як комахи та квіти) з дуже короткими термінами життя. Незабаром після цього , він набув розширеного сенсу, посилаючись на все швидкоплинне і короткочасне (як у «ефемерних задоволеннях») ».
— Остін Д

1
Що мені також подобається у цій відповіді, це те, що в ньому згадується, що JPA розглядає transientполя як неявні @Transientанотації. Отже, якщо ви використовуєте transientключове слово для запобігання серіалізації поля, воно також не опиниться в базі даних.
— neXus

17

Якщо ви просто хочете, щоб поле не залишалося збереженим, і тимчасові, і транзитні роботи. Але питання в тому, чому @Transient, оскільки перехідний, вже існує.

Тому що поле @Transient все ще буде серіалізовано!

Припустимо, ви створили сутність, зробивши певний обчислювач процесора, щоб отримати результат, і цей результат не збережеться в базі даних. Але ви хочете надіслати об'єкт іншим Java-програмам для використання JMS, тоді ви повинні використовувати @Transient, а не ключове слово JavaSE transient. Таким чином, приймачі, що працюють на інших VM, можуть заощадити свій час на повторний розрахунок.


Ви можете надати приклад, щоб зробити це більш зрозумілим?
— Суворий Канахара

Чи є зауваження, що jpa вважатиме тимчасовим, але Джексон не буде?
— Калпеш Соні

0

Я спробую відповісти на питання "чому". Уявіть ситуацію, коли у вас є величезна база даних з великою кількістю стовпців у таблиці, а ваш проект / система використовує інструменти для генерації об'єктів із бази даних. (У сплячому режимі є такі, і т. Д.) Тепер, припустимо, що за вашою діловою логікою вам потрібно певне поле, яке НЕ слід зберігати. Ви повинні "налаштувати" свою організацію певним чином. Хоча ключове слово Transient працює на об'єкті - оскільки він поводиться в рамках мови java, @Transient призначений лише для відповіді на завдання, що стосуються лише завдань, що зберігаються.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.