Odpowiedzi:
@Transient odpowiada Twoim potrzebom.
Aby zignorować pole, opatrz je adnotacją, @Transientaby 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;
@JsonIncludenie jest konieczne: @Transientpola 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ą, @Transientaby 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ą accounttabelę:
accountStół jest mapowany do Accountpodmiotu 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, centsto podstawowe atrybuty.
Ale dollars, interestCentsi interestDollarssą obliczane właściwości, więc opisywać je @Transientwyłą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 posti post_commenttabele:
Chcesz zmapować lastestComment powiązanie w Postencji 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 latestCommentjest ona pobierana, ale jeśli chcesz ją zmodyfikować, zmiana zostanie zignorowana.
Tak więc, w przypadku skojarzeń, możesz użyć
@JoinFormulaaby 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:
PostDetailsJednostka 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 idatrybut, jak i postpowiązanie odwzorowują tę samą kolumnę bazy danych, która jest post_detailskolumną Klucz podstawowy.
Aby wykluczyć idatrybut, @MapsIdadnotacja poinformuje Hibernację, że postskojarzenie 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ć,
@MapsIdaby 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 = falseInną 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 insertablei updatableatrybuty @JoinColumnadnotacji poinstruuje Hibernate zignorować poststowarzyszenie ponieważ podmiot identyfikator dba o post_idkolumnie klucz podstawowy.
posti post_detailstabel 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, @Transientchyba ż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_ANNOTATIONfunkcji 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!