Java имеет ключевое слово transient
. Почему JPA имеет @Transient
вместо простого использования уже существующего ключевого слова java?
Почему JPA имеет аннотацию @Transient?
Ответ 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 предназначен только для ответа на задачи, которые относятся только к задачам сохранения.