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

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

Ответ 1

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

Ответ 2

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

Ответ 3

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

Ответ 4

Назначение другое:

Ключевое слово transient и аннотация @Transient имеют две разные цели: речь идет о сериализации, а речь идет о сохранении. Как программисты, мы часто вступаем в брак с этими двумя концепциями в один, но это не совсем точно. Persistence относится к характеристике состояния, которое переживает процесс, который его создал. Сериализация в 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.

Ответ 5

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

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

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

Ответ 6

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