Ответы:
@Transient
соответствует вашим потребностям.
Чтобы игнорировать поле, пометьте его, @Transient
чтобы оно не отображалось в спящем режиме.
но тогда Джексон не будет сериализовать поле при преобразовании в JSON.
Если вам нужно смешать JPA с JSON (опускается JPA, но все еще включается в Джексона), используйте @JsonInclude
:
@JsonInclude()
@Transient
private String token;
НАКОНЕЧНИК:
Вы также можете использовать JsonInclude.Include.NON_NULL и скрывать поля в JSON во время десериализации, когда token == null
:
@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
private String token;
@JsonInclude
нет необходимости: @Transient
поля все еще включены в JSON. (Вы все еще получили мой голос: сама техника может быть очень полезна в других обстоятельствах).
Чтобы игнорировать поле, пометьте его, @Transient
чтобы оно не отображалось в спящем режиме.
Источник: Hibernate Аннотации .
Этот ответ приходит немного поздно, но он завершает ответ.
Во избежание сохранения поля из сущности в БД можно использовать один из двух механизмов:
@Transient - аннотация JPA, помечающая поле как нестабильное
временное ключевое слово в Java. Осторожно - использование этого ключевого слова предотвратит использование поля с любым механизмом сериализации из Java. Итак, если поле должно быть сериализовано, вам лучше использоватьаннотацию @Transient .
Существует несколько решений в зависимости от типа атрибута объекта.
Предположим, у вас есть следующая account
таблица:
account
Таблица отображается в Account
сущности , как это:
@Entity(name = "Account")
public class Account {
@Id
private Long id;
@ManyToOne
private User owner;
private String iban;
private long cents;
private double interestRate;
private Timestamp createdOn;
@Transient
private double dollars;
@Transient
private long interestCents;
@Transient
private double interestDollars;
@PostLoad
private void postLoad() {
this.dollars = cents / 100D;
long months = createdOn.toLocalDateTime()
.until(LocalDateTime.now(), ChronoUnit.MONTHS);
double interestUnrounded = ( ( interestRate / 100D ) * cents * months ) / 12;
this.interestCents = BigDecimal.valueOf(interestUnrounded)
.setScale(0, BigDecimal.ROUND_HALF_EVEN).longValue();
this.interestDollars = interestCents / 100D;
}
//Getters and setters omitted for brevity
}
Основные атрибуты сущностей отображаются в столбцах таблицы, поэтому свойства , такие как id
, iban
, cents
являются основными атрибутами.
Но dollars
, interestCents
и interestDollars
вычисляются свойства, так что вы аннотировать их , @Transient
чтобы исключить их из SELECT, INSERT, UPDATE и DELETE заявления SQL.
Итак, для базовых атрибутов вам нужно использовать
@Transient
, чтобы исключить сохранение данного свойства.Для получения дополнительной информации о вычисляемых атрибутах сущности, ознакомьтесь с этой статьей .
Предполагая, что у вас есть следующее post
и post_comment
таблицы:
Вы хотите сопоставить lastestComment
ассоциацию в Post
сущности с последней PostComment
добавленной сущностью.
Для этого вы можете использовать @JoinFormula
аннотацию:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
private Long id;
private String title;
@ManyToOne(fetch = FetchType.LAZY)
@JoinFormula("(" +
"SELECT pc.id " +
"FROM post_comment pc " +
"WHERE pc.post_id = id " +
"ORDER BY pc.created_on DESC " +
"LIMIT 1" +
")")
private PostComment latestComment;
//Getters and setters omitted for brevity
}
При извлечении Post
сущности вы можете видеть, что latestComment
она извлекается, но если вы хотите изменить ее, изменение будет проигнорировано.
Таким образом, для ассоциаций вы можете использовать,
@JoinFormula
чтобы игнорировать операции записи, но при этом разрешать чтение ассоциации.Для более подробной информации о вычисляемых ассоциациях, посмотрите эту статью .
Другой способ игнорировать ассоциации, которые уже сопоставлены идентификатором объекта, - использовать @MapsId
.
Например, рассмотрим следующую взаимосвязь таблицы «один к одному»:
PostDetails
Объект отображается следующим образом:
@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
}
Обратите внимание, что и id
атрибут, и post
сопоставление отображают один и тот же столбец базы данных, который является post_details
столбцом первичного ключа.
Чтобы исключить id
атрибут, @MapsId
аннотация сообщит Hibernate, что post
ассоциация заботится о значении столбца первичного ключа таблицы.
Таким образом, когда идентификатор объекта и ассоциация совместно используют один и тот же столбец, вы можете использовать,
@MapsId
чтобы игнорировать атрибут идентификатора объекта и использовать вместо него ассоциацию.Для более подробной информации
@MapsId
, ознакомьтесь с этой статьей .
insertable = false, updatable = false
Другой вариант - использовать insertable = false, updatable = false
для ассоциации, которую вы хотите игнорировать в Hibernate.
Например, мы можем сопоставить предыдущую однозначную ассоциацию следующим образом:
@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {
@Id
@Column(name = "post_id")
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne
@JoinColumn(name = "post_id", insertable = false, updatable = false)
private Post post;
//Getters and setters omitted for brevity
public void setPost(Post post) {
this.post = post;
if (post != null) {
this.id = post.getId();
}
}
}
В insertable
и updatable
атрибутах @JoinColumn
аннотации будут инструктировать Hibernate игнорировать post
ассоциацию с момента субъекта идентификатора заботится о post_id
столбце первичного ключа.
post
и post_details
таблиц в качестве примера?
Ни один из приведенных выше ответов не работал для меня, используя Hibernate 5.2.10, Jersey 2.25.1 и Jackson 2.8.9. Я наконец нашел ответ (вроде как они ссылаются на hibernate4module, но он работает и для 5) здесь . Ни одна из аннотаций Json не работала вообще @Transient
. Очевидно, Jackson2 достаточно «умен», чтобы любезно игнорировать вещи, помеченные значком, @Transient
если вы явно не скажете этого не делать. Ключом было добавить модуль hibernate5 (который я использовал для работы с другими аннотациями Hibernate) и отключить эту USE_TRANSIENT_ANNOTATION
функцию в моем приложении на Джерси:
ObjectMapper jacksonObjectMapper = new ObjectMapper();
Hibernate5Module jacksonHibernateModule = new Hibernate5Module();
jacksonHibernateModule.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
jacksonObjectMapper.registerModule(jacksonHibernateModule);
Вот зависимость для Hibernate5Module:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.8.9</version>
</dependency>
@JsonProperty
@JsonInclude
@JsonSerialize + @JsonDeserialize
mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, false));
это решение, наконец, сработало. Спасибо!
Иногда вы хотите:
использование @Column(name = "columnName", insertable = false, updatable = false)
Хороший сценарий - это когда определенный столбец автоматически вычисляется с использованием других значений столбца.