Odpowiedzi:
@Transient
odpowiada Twoim potrzebom.
Aby zignorować pole, opatrz je adnotacją, @Transient
aby nie było mapowane przez hibernację.
ale wtedy Jackson nie serializuje pola podczas konwersji na JSON.
Jeśli potrzebujesz wymieszać JPA z JSON (pomiń JPA, ale nadal dołączasz do Jacksona) użyj @JsonInclude
:
@JsonInclude()
@Transient
private String token;
WSKAZÓWKA:
Możesz także użyć JsonInclude.Include.NON_NULL i ukryć pola w JSON podczas deserializacji, gdy token == null
:
@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
private String token;
@JsonInclude
nie jest konieczne: @Transient
pola są nadal zawarte w JSON. (Nadal masz mój głos: sama technika może być bardzo przydatna w innych okolicznościach).
Aby zignorować pole, oznacz je adnotacją, @Transient
aby nie było mapowane przez hibernację.
Źródło: Hibernacja Adnotacje .
Ta odpowiedź przychodzi trochę później, ale uzupełnia odpowiedź.
Aby uniknąć utrwalenia pola z encji w DB, można użyć jednego z dwóch mechanizmów:
@Transient - adnotacja JPA oznaczająca pole jako nietrwałe
przejściowe słowo kluczowe w java. Uwaga - użycie tego słowa kluczowego uniemożliwi użycie pola z dowolnym mechanizmem serializacji z języka Java. Tak więc, jeśli pole musi być zserializowane, lepiej użyć tylkoadnotacji @Transient .
Istnieje wiele rozwiązań w zależności od typu atrybutu encji.
Rozważ, że masz następującą account
tabelę:
account
Stół jest mapowany do Account
podmiotu takiego:
@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
}
Podstawowe atrybuty podmiotu są odwzorowane do kolumn tabeli, więc właściwości podoba id
, iban
, cents
to podstawowe atrybuty.
Ale dollars
, interestCents
i interestDollars
są obliczane właściwości, więc opisywać je @Transient
wyłączyć je z SELECT, INSERT, UPDATE i DELETE SQL.
Zatem w przypadku podstawowych atrybutów należy użyć
@Transient
, aby wykluczyć utrwalenie danej właściwości.Aby uzyskać więcej informacji na temat atrybutów jednostki obliczanej, sprawdź ten artykuł .
Zakładając, że masz następujące elementy post
i post_comment
tabele:
Chcesz zmapować lastestComment
powiązanie w Post
encji na najnowszą PostComment
, która została dodana.
Aby to zrobić, możesz użyć @JoinFormula
adnotacji:
@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
}
Podczas pobierania Post
encji widać, że latestComment
jest ona pobierana, ale jeśli chcesz ją zmodyfikować, zmiana zostanie zignorowana.
Tak więc, w przypadku skojarzeń, możesz użyć
@JoinFormula
aby zignorować operacje zapisu, jednocześnie umożliwiając odczytanie powiązania.Aby uzyskać więcej informacji o skojarzeniach obliczeniowych, sprawdź ten artykuł .
Innym sposobem na zignorowanie powiązań, które są już zamapowane przez identyfikator jednostki, jest użycie @MapsId
.
Rozważmy na przykład następującą relację jeden do jednego:
PostDetails
Jednostka jest odwzorowany tak:
@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
}
Zauważ, że zarówno id
atrybut, jak i post
powiązanie odwzorowują tę samą kolumnę bazy danych, która jest post_details
kolumną Klucz podstawowy.
Aby wykluczyć id
atrybut, @MapsId
adnotacja poinformuje Hibernację, że post
skojarzenie zajmuje się wartością kolumny Klucz podstawowy tabeli.
Tak więc, gdy identyfikator jednostki i powiązanie mają tę samą kolumnę, możesz użyć,
@MapsId
aby zignorować atrybut identyfikatora jednostki i zamiast tego użyć powiązania.Aby uzyskać więcej informacji na temat
@MapsId
, sprawdź ten artykuł .
insertable = false, updatable = false
Inną opcją jest użycie insertable = false, updatable = false
powiązania, które ma być ignorowane przez Hibernację.
Na przykład możemy zmapować poprzednie powiązanie jeden do jednego w następujący sposób:
@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();
}
}
}
Te insertable
i updatable
atrybuty @JoinColumn
adnotacji poinstruuje Hibernate zignorować post
stowarzyszenie ponieważ podmiot identyfikator dba o post_id
kolumnie klucz podstawowy.
post
i post_details
tabel jako przykładu?
Żadna z powyższych odpowiedzi nie działała dla mnie przy użyciu Hibernacji 5.2.10, Jersey 2.25.1 i Jackson 2.8.9. W końcu znalazłem odpowiedź (w pewnym sensie, odwołują się one do hibernacji4moduła, ale działa również dla 5) tutaj . Żadna adnotacja Jsona w ogóle nie działała @Transient
. Najwyraźniej Jackson2 jest „wystarczająco inteligentny”, aby uprzejmie zignorować rzeczy oznaczone, @Transient
chyba że wyraźnie to powiesz. Kluczem było dodanie modułu hibernacji5 (którego używałem do obsługi innych adnotacji Hibernacji) i wyłączenie tej USE_TRANSIENT_ANNOTATION
funkcji w mojej aplikacji Jersey:
ObjectMapper jacksonObjectMapper = new ObjectMapper();
Hibernate5Module jacksonHibernateModule = new Hibernate5Module();
jacksonHibernateModule.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
jacksonObjectMapper.registerModule(jacksonHibernateModule);
Oto zależność dla 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));
to rozwiązanie w końcu zadziałało. Dzięki!