Почему JPA имеет аннотацию @Transient?

283

У Java есть transientключевое слово. Почему JPA @Transientвместо простого использования уже существующего ключевого слова Java?

Deamon
источник

Ответы:

455

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

Jawher
источник
3
Да, семантика различна. Но почему JPA был разработан таким образом?
Дилум Ранатунга
1
Не уверен, что я вас понимаю, но взгляните на ответ «Паскаля Тивента»;)
Jawher
30
Это удобно, потому что вы, возможно, не захотите хранить данные в базе данных, но вы действительно хотите сохранить их в системе JPA Chaching, которая использует сериализацию для сохранения / восстановления сущностей.
Kdeveloper
1
Что такое «система кэширования JPA», которая использует сериализацию для сохранения / восстановления сущностей? Реализация JPA может кэшировать объект любым образом, и сериализация в него не входит.
DataNucleus 20.10.10
@Jawher, здесь для переходного непрезистентного означает не иметь никакого значения, или он вставит значение по умолчанию для этого атрибута.
Сатиш Шарма
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, можете ли вы объяснить, почему и как это может привести к неопределенному поведению? Спасибо!
Тайдукман
@ 40Plot спецификация гласит так
psp
7
Это должно быть ИМХО принятым ответом, так как он намного больше объясняет, что нынешний принятый ответ ...
Хонза Зидек
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 напрямую, без использования ProgressReport.

Остин Д
источник
1
Если на самом деле это разные проблемы, наверняка существует другое слово, которое улавливает нюансы. Зачем перегружать термин? В качестве начального предложения @Unpersisted.
Дилум Ранатунга
4
Мне лично нравится @Ephemeral. Согласно Merriam Webster: когда эфемерное впервые было напечатано на английском языке в 1600-х годах, «это был научный термин, применяемый к кратковременным лихорадкам, а затем к организмам (таким как насекомые и цветы) с очень короткими периодами жизни. Вскоре после этого оно приобрело расширенный смысл, относящийся ко всему мимолетному и недолговечному (как в «эфемерных удовольствиях») ».
Остин D
1
Что мне также нравится в этом ответе, так это то, что в нем упоминается, что JPA считает transientполя неявно имеющими @Transientаннотацию. Поэтому, если вы используете transientключевое слово для предотвращения сериализации поля, оно также не попадет в базу данных.
neXus
17

Если вы просто хотите, чтобы поле не сохранялось, работают как переходные, так и @Transient . Но вопрос в том, почему @Transient, так как переходный процесс уже существует.

Потому что поле @Transient все равно будет сериализовано!

Предположим, вы создали сущность, выполнив некоторое потребление ресурсов процессора, чтобы получить результат, и этот результат не будет сохранен в базе данных. Но вы хотите отправить объект в другие приложения Java для использования JMS, тогда вам следует использовать @Transient, а не ключевое слово JavaSE transient. Таким образом, получатели, работающие на других виртуальных машинах, могут сэкономить свое время для повторного расчета.

Sheng.W
источник
Можете ли вы привести пример, чтобы сделать его более понятным?
Суровая Канахара
есть ли аннотация, что jpa будет рассматривать как переходный процесс, но Джексон не будет?
Кальпеш Сони
0

Я постараюсь ответить на вопрос «почему». Представьте себе ситуацию, когда у вас есть огромная база данных с большим количеством столбцов в таблице, и ваш проект / система использует инструменты для создания сущностей из базы данных. (У Hibernate есть такие и т. Д.). Теперь предположим, что в соответствии с вашей бизнес-логикой вам нужно определенное поле, НЕ подлежащее сохранению. Вы должны «настроить» свою сущность определенным образом. В то время как ключевое слово Transient работает с объектом - так как оно ведет себя в языке Java, @Transient предназначен только для решения задач, относящихся только к задачам сохранения.

Дима Р.
источник