Чому 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.