Ich arbeite an SpringMVC
, Hibernate
& JSON
aber ich diese Störung erhalte.
HTTP Status 500 - Could not write JSON: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.SerializationFeature.FAIL_ON_EMPTY_BEANS) )
Bitte überprüfen Sie meine Entität unten
@Entity
@Table(name="USERS")
public class User {
@Id
@GeneratedValue
@Column(name="USER_ID")
private Integer userId;
@Column(name="USER_FIRST_NAME")
private String firstName;
@Column(name="USER_LAST_NAME")
private String lastName;
@Column(name="USER_MIDDLE_NAME")
private String middleName;
@Column(name="USER_EMAIL_ID")
private String emailId;
@Column(name="USER_PHONE_NO")
private Integer phoneNo;
@Column(name="USER_PASSWORD")
private String password;
@Column(name="USER_CONF_PASSWORD")
private String confPassword;
@Transient
private String token;
@Column(name="USER_CREATED_ON")
private Date createdOn;
@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
@Fetch(value = FetchMode.SUBSELECT)
@JoinTable(name = "USER_ROLES", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
private List<ActifioRoles> userRole = new ArrayList<ActifioRoles>();
@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL,mappedBy="userDetails")
@Fetch(value = FetchMode.SUBSELECT)
private List<com.actifio.domain.Address> userAddress = new ArrayList<com.actifio.domain.Address>();
@OneToOne(cascade=CascadeType.ALL)
private Tenant tenantDetails;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getConfPassword() {
return confPassword;
}
public void setConfPassword(String confPassword) {
this.confPassword = confPassword;
}
public Date getCreatedOn() {
return createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
public List<ActifioRoles> getUserRole() {
return userRole;
}
public void setUserRole(List<ActifioRoles> userRole) {
this.userRole = userRole;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public Integer getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(Integer phoneNo) {
this.phoneNo = phoneNo;
}
public List<com.actifio.domain.Address> getUserAddress() {
return userAddress;
}
public void setUserAddress(List<com.actifio.domain.Address> userAddress) {
this.userAddress = userAddress;
}
public Tenant getTenantDetails() {
return tenantDetails;
}
public void setTenantDetails(Tenant tenantDetails) {
this.tenantDetails = tenantDetails;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
Wie kann ich das lösen?
Antworten:
Ich hatte ein ähnliches Problem mit dem verzögerten Laden über das Ruhezustand-Proxy-Objekt. Ich habe es umgangen, indem ich die Klasse mit faulen geladenen privaten Eigenschaften mit folgenden Anmerkungen versehen habe:
Ich gehe davon aus, dass Sie die Eigenschaften Ihres Proxy-Objekts, die die JSON-Serialisierung unterbrechen, zu dieser Annotation hinzufügen können.
Das Problem ist, dass Entitäten träge geladen werden und die Serialisierung erfolgt, bevor sie vollständig geladen werden.
quelle
Um dies hinzuzufügen, bin ich auf dasselbe Problem gestoßen, aber die bereitgestellten Antworten haben nicht funktioniert. Ich habe das Problem behoben, indem ich den Vorschlag der Ausnahme aufgegriffen und zur Datei application.properties hinzugefügt habe ...
Ich verwende Spring Boot v1.3 mit Hibernate 4.3
Es serialisiert jetzt das gesamte Objekt und verschachtelte Objekte.
EDIT: 2018
Da dies noch Kommentare bekommt, werde ich hier klarstellen. Dies verbirgt absolut nur den Fehler. Die Auswirkungen auf die Leistung sind da. Zu der Zeit brauchte ich etwas, um es zu liefern und später daran zu arbeiten (was ich tat, indem ich keine Feder mehr benutzte). Also ja, hören Sie jemand anderem zu, wenn Sie das Problem wirklich lösen möchten. Wenn Sie es erst einmal weg haben möchten, verwenden Sie diese Antwort. Es ist eine schreckliche Idee, aber zum Teufel, könnte für Sie arbeiten. Für die Aufzeichnung, hatte nie wieder einen Absturz oder ein Problem danach. Aber es ist wahrscheinlich die Quelle eines SQL-Performance-Alptraums.
quelle
"handler":{},"hibernateLazyInitializer":{}
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Wie in früheren Antworten richtig vorgeschlagen, bedeutet verzögertes Laden, dass beim Abrufen Ihres Objekts aus der Datenbank die verschachtelten Objekte nicht abgerufen werden (und bei Bedarf möglicherweise später abgerufen werden).
Jetzt versucht Jackson, das verschachtelte Objekt zu serialisieren (== JSON daraus zu machen), schlägt jedoch fehl, da JavassistLazyInitializer anstelle des normalen Objekts gefunden wird. Dies ist der Fehler, den Sie sehen. Wie kann man das lösen?
Wie zuvor von CP510 vorgeschlagen, besteht eine Option darin, den Fehler durch diese Konfigurationszeile zu unterdrücken:
Aber es geht um die Symptome, nicht um die Ursache . Um es elegant zu lösen, müssen Sie entscheiden, ob Sie dieses Objekt in JSON benötigen oder nicht.
Wenn Sie das Objekt in JSON benötigen, entfernen Sie die
FetchType.LAZY
Option aus dem Feld, das sie verursacht (es kann sich auch um ein Feld in einem verschachtelten Objekt handeln, nicht nur in der Stammentität, die Sie abrufen).Wenn Sie das Objekt in JSON nicht benötigen, kommentieren Sie den Getter dieses Felds (oder das Feld selbst, wenn Sie auch keine eingehenden Werte akzeptieren müssen) mit
@JsonIgnore
:// this field will not be serialized to/from JSON @JsonIgnore private NestedType secret;
Wenn Sie komplexere Anforderungen haben (z. B. unterschiedliche Regeln für unterschiedliche REST-Controller, die dieselbe Entität verwenden), können Sie Jackson- Ansichten oder -Filter verwenden oder für einen sehr einfachen Anwendungsfall verschachtelte Objekte separat abrufen .
quelle
RangeError: Maximum call stack size exceeded
Sie können das Zusatzmodul für Jackson verwenden, das das verzögerte Laden im Ruhezustand übernimmt.
Weitere Informationen unter https://github.com/FasterXML/jackson-datatype-hibernate , die den Ruhezustand 3 und 4 separat unterstützen.
quelle
Ich denke, dass das Problem darin besteht, wie Sie die Entität abrufen.
Vielleicht machst du so etwas:
Versuchen Sie es mit der Methode
get
anstelle vonload
Das Problem ist, dass Sie mit der Lademethode nur einen Proxy erhalten, aber nicht das eigentliche Objekt. Für das Proxy-Objekt sind die Eigenschaften noch nicht geladen. Wenn die Serialisierung erfolgt, müssen keine Eigenschaften serialisiert werden. Mit der get-Methode erhalten Sie tatsächlich das reale Objekt, dieses Objekt könnte tatsächlich serialisiert werden.
quelle
Für mich geht das
z.B
quelle
Es gibt zwei Möglichkeiten, um das Problem zu beheben.
Weg 1 :
spring.jackson.serialization.fail-on-empty-beans=false
In application.properties hinzufügenWeg 2 :
Verwendung
join fetch
in JPQL Abfrage übergeordnetes Objekt Daten abrufen, siehe unten:quelle
Fügen Sie diese Anmerkung zur Entitätsklasse (Modell) hinzu, die für mich funktioniert, da dies zu einem verzögerten Laden über das Proxy-Objekt im Ruhezustand führt.
quelle
Diese Ausnahme
Ich hoffe, Sie senden eine Antwortausgabe als serialisierbares Objekt.
Dies ist ein Problem, das im Frühjahr auftritt. Um dieses Problem zu beheben, senden Sie das POJO-Objekt als Antwortausgabe.
Beispiel:
POJO-Klasse:
In der Steuerung konvertieren Sie die serilisierbaren Objektfelder in POJO-Klassenfelder und geben die Pojo-Klasse als Ausgabe zurück.
quelle
In Hibernate 5.2 und höher können Sie den Hibernate-Proxy wie folgt entfernen. Dadurch erhalten Sie das eigentliche Objekt, damit Sie es ordnungsgemäß serialisieren können:
quelle
Hibernate.initialize
vorher automatisch angerufen .Für den Ruhezustand können Sie den Jackson-Datentyp-Ruhezustand verwenden Projekt , um die JSON-Serialisierung / -Deserialisierung mit verzögert geladenen Objekten zu ermöglichen.
Beispielsweise,
quelle
can't parse JSON. Raw result:
. Irgendeine Hilfe?Die Lösung ist von der folgenden Lösung von @marco inspiriert. Ich habe auch seine Antwort mit diesen Daten aktualisiert.
Das Problem hierbei ist das verzögerte Laden der Unterobjekte, bei denen Jackson nur Proxys im Ruhezustand anstelle von vollständigen Objekten findet.
Wir haben also zwei Möglichkeiten: Unterdrücken Sie die Ausnahme, wie oben in der Antwort mit den meisten Abstimmungen hier beschrieben, oder stellen Sie sicher, dass die LazyLoad-Objekte geladen sind.
Wenn Sie sich für die letztere Option entscheiden, besteht die Lösung darin, die Jackson-Datentypbibliothek zu verwenden und die Bibliothek so zu konfigurieren, dass Abhängigkeiten beim verzögerten Laden vor der Serialisierung initialisiert werden.
Ich habe dazu eine neue Konfigurationsklasse hinzugefügt.
}}
@Primary
stellt sicher, dass keine andere Jackson-Konfiguration zum Initialisieren anderer Beans verwendet wird.@Bean
ist wie immer.module.enable(Hibernate5Module.Feature.FORCE_LAZY_LOADING);
soll das verzögerte Laden der Abhängigkeiten aktivieren.Achtung - Bitte achten Sie auf die Auswirkungen auf die Leistung. Manchmal hilft EAGER-Abruf, aber selbst wenn Sie es eifrig machen, benötigen Sie diesen Code immer noch, da Proxy-Objekte für alle anderen Zuordnungen außer noch vorhanden sind
@OneToOne
PS: Als allgemeinen Kommentar würde ich davon abraten, ganze Datenobjekte in der Json-Antwort zurückzusenden. Man sollte Dto's für diese Kommunikation verwenden und einen Mapper wie mapstruct verwenden, um sie abzubilden. Dies erspart Ihnen versehentliche Sicherheitslücken sowie die oben genannten Ausnahmen.
quelle
Ich habe jetzt das gleiche Problem. Überprüfen Sie, ob Sie Fetch in Lazy mit einem @jsonIQgnore beheben
Löschen Sie einfach "(fetch = ...)" oder die Anmerkung "@jsonIgnore" und es wird funktionieren
quelle
Oder Sie können Mapper wie folgt konfigurieren:
// benutzerdefinierte Konfiguration für verzögertes Laden
und Mapper konfigurieren:
quelle
Es könnte sich um Ihre Entität im Ruhezustand handeln, die das Problem verursacht. Beenden Sie einfach das verzögerte Laden dieser verwandten Entität. Beispiel: Ich habe das Problem unten gelöst, indem ich für customerType faul = "false" gesetzt habe.
quelle
Ich habe mich geändert (in der Annotation-Modellklasse)
zu
und auf hübsche Weise gearbeitet ...
Liebe es.
quelle
fetch
Strategie für ein Modell hat mehrere Konsequenzen für die Leistung. Mit dieser Änderung bringen Sie viel mehr Daten aus der Datenbank. Es mag eine gültige Lösung sein, aber zuerst ist eine Leistungsstudie erforderlich.Dies ist ein Problem mit Jackson. Um dies zu verhindern, weisen Sie Jackson an, keine verschachtelten Beziehungen oder verschachtelten Klassen zu serialisieren.
Schauen Sie sich das folgende Beispiel an. Adressklasse, die den Klassen Stadt , Bundesland und Land zugeordnet ist , und der Staat selbst zeigt auf Land und Land auf Region. Wenn Sie Adresswerte über die Spring Boot REST-API abrufen, wird der obige Fehler angezeigt. Um dies zu verhindern, serialisieren Sie einfach die zugeordnete Klasse (die JSON der ersten Ebene widerspiegelt) und ignorieren Sie verschachtelte Beziehungen mit
@JsonIgnoreProperties(value = {"state"})
,@JsonIgnoreProperties(value = {"country"})
und@JsonIgnoreProperties(value = {"region"})
Dies verhindert eine Lazyload-Ausnahme zusammen mit dem obigen Fehler. Verwenden Sie den folgenden Code als Beispiel und ändern Sie Ihre Modellklassen.
Address.java
City.java
State.java
Country.java
quelle
Versuchen
implements interface Serializable
quelle