Réponses:
@Transient
répond à vos besoins.
Pour ignorer un champ, annotez-le avec @Transient
afin qu'il ne soit pas mappé en hibernation.
mais jackson ne sérialisera pas le champ lors de la conversion en JSON.
Si vous avez besoin de mélanger JPA avec JSON (omis par JPA mais toujours inclus dans Jackson), utilisez @JsonInclude
:
@JsonInclude()
@Transient
private String token;
POINTE:
Vous pouvez également utiliser JsonInclude.Include.NON_NULL et masquer les champs dans JSON pendant la désérialisation lorsque token == null
:
@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
private String token;
@JsonInclude
n'est pas nécessaire: les @Transient
champs sont toujours inclus dans JSON. (Vous avez quand même obtenu mon vote: la technique elle-même pourrait être très utile dans d'autres circonstances).
Pour ignorer un champ, annotez-le avec @Transient
afin qu'il ne soit pas mappé en hibernation.
Source: Hibernate Annotations .
Cette réponse arrive un peu tard, mais elle complète la réponse.
Afin d'éviter qu'un champ d'une entité ne persiste dans la base de données, on peut utiliser l'un des deux mécanismes:
@Transient - l'annotation JPA marquant un champ comme non persistant
mot-clé transitoire en java. Attention - l'utilisation de ce mot-clé empêchera le champ d'être utilisé avec tout mécanisme de sérialisation de java. Donc, si le champ doit être sérialisé, vous feriez mieux d'utiliser uniquement l'annotation @Transient .
Il existe plusieurs solutions selon le type d'attribut d'entité.
Considérez que vous avez le account
tableau suivant :
Le account
tableau est mappé à l' Account
entité comme ceci:
@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
}
Les attributs des entités de base sont mis en correspondance avec des colonnes de table, donc des propriétés telles que id
, iban
, cents
sont des attributs de base.
Mais dollars
, interestCents
et interestDollars
sont des propriétés calculées, afin que vous les annoter avec @Transient
les exclure de SELECT, INSERT, UPDATE et DELETE SQL.
Ainsi, pour les attributs de base, vous devez utiliser
@Transient
afin d'exclure une propriété donnée de la persistance.Pour plus de détails sur les attributs d'entité calculés, consultez cet article .
En supposant que vous disposez des éléments suivants post
et des post_comment
tableaux:
Vous souhaitez mapper l' lastestComment
association dans l' Post
entité à la dernière PostComment
entité ajoutée.
Pour ce faire, vous pouvez utiliser l' @JoinFormula
annotation:
@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
}
Lors de la récupération de l' Post
entité, vous pouvez voir que le latestComment
est récupéré, mais si vous souhaitez le modifier, le changement va être ignoré.
Ainsi, pour les associations, vous pouvez utiliser
@JoinFormula
pour ignorer les opérations d'écriture tout en autorisant la lecture de l'association.Pour plus de détails sur les associations calculées, consultez cet article .
Une autre façon d'ignorer les associations déjà mappées par l'identifiant d'entité est d'utiliser @MapsId
.
Par exemple, considérez la relation de table un-à-un suivante:
L' PostDetails
entité est mappée comme ceci:
@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
}
Notez que l' id
attribut et l' post
association mappent la même colonne de base de données, qui est la post_details
colonne Clé primaire.
Pour exclure l' id
attribut, l' @MapsId
annotation indiquera à Hibernate que l' post
association prend en charge la valeur de la colonne Clé primaire de la table.
Ainsi, lorsque l'identifiant d'entité et une association partagent la même colonne, vous pouvez utiliser
@MapsId
pour ignorer l'attribut d'identifiant d'entité et utiliser l'association à la place.Pour plus de détails sur
@MapsId
, consultez cet article .
insertable = false, updatable = false
Une autre option consiste à utiliser insertable = false, updatable = false
pour l'association que vous souhaitez ignorer par Hibernate.
Par exemple, nous pouvons mapper l'association biunivoque précédente comme ceci:
@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();
}
}
}
Les attributs insertable
et updatable
de l' @JoinColumn
annotation indiqueront à Hibernate d'ignorer l' post
association car l'identifiant d'entité prend en charge la post_id
colonne Clé primaire.
post
et post_details
comme exemple?
Aucune des réponses ci-dessus n'a fonctionné pour moi en utilisant Hibernate 5.2.10, Jersey 2.25.1 et Jackson 2.8.9. J'ai finalement trouvé la réponse (en quelque sorte, ils font référence à hibernate4module mais cela fonctionne aussi pour 5) ici . Aucune des annotations Json n'a fonctionné du tout @Transient
. Apparemment, Jackson2 est suffisamment «intelligent» pour ignorer les choses marquées par, à @Transient
moins que vous ne le lui disiez explicitement. La clé était d'ajouter le module hibernate5 (que j'utilisais pour gérer d'autres annotations Hibernate) et de désactiver la USE_TRANSIENT_ANNOTATION
fonctionnalité dans mon application Jersey:
ObjectMapper jacksonObjectMapper = new ObjectMapper();
Hibernate5Module jacksonHibernateModule = new Hibernate5Module();
jacksonHibernateModule.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
jacksonObjectMapper.registerModule(jacksonHibernateModule);
Voici la dépendance du 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));
cette solution a finalement fonctionné. Merci!