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


283

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

Ответы:


455

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


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. Таким образом, получатели, работающие на других виртуальных машинах, могут сэкономить свое время для повторного расчета.


Можете ли вы привести пример, чтобы сделать его более понятным?
— Суровая Канахара

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

0

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.