Почему JPA имеет аннотацию @Transient? - PullRequest
249 голосов
/ 28 января 2010

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

Ответы [ 6 ]

392 голосов
/ 28 января 2010

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

105 голосов
/ 28 января 2010

Потому что они имеют разные значения. Аннотация @Transient указывает провайдеру JPA не сохранять какой-либо (не transient) атрибут. Другой говорит платформе сериализации не сериализовать атрибут. Возможно, вы захотите иметь свойство @Transient и все же его сериализовать.

86 голосов
/ 28 января 2010

Как уже говорили другие, @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 вообще.

40 голосов
/ 26 февраля 2016

Цель другая:

Ключевое слово 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.

17 голосов
/ 18 ноября 2015

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

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

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

0 голосов
/ 16 декабря 2015

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

...