Je travaille sur SpringMVC
, Hibernate
et JSON
mais je reçois cette erreur.
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) )
Veuillez vérifier mon entité ci-dessous
@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;
}
}
Comment puis-je resoudre ceci?
Réponses:
J'ai eu un problème similaire avec le chargement paresseux via l'objet proxy d'hibernation. Contournez-le en annotant la classe ayant des propriétés privées chargées paresseusement avec:
Je suppose que vous pouvez ajouter les propriétés de votre objet proxy qui interrompent la sérialisation JSON à cette annotation.
Le problème est que les entités sont chargées paresseusement et que la sérialisation se produit avant qu'elles ne soient complètement chargées.
la source
Juste pour ajouter cela, j'ai rencontré le même problème, mais les réponses fournies n'ont pas fonctionné. Je l'ai corrigé en prenant la suggestion de l'exception et en l'ajoutant au fichier application.properties ...
J'utilise Spring Boot v1.3 avec Hibernate 4.3
Il sérialise désormais l'objet entier et les objets imbriqués.
MODIFIER: 2018
Comme cela reçoit encore des commentaires, je vais clarifier ici. Cela ne cache absolument que l'erreur. Les implications sur les performances sont là. À l'époque, j'avais besoin de quelque chose pour livrer et travailler dessus plus tard (ce que j'ai fait en n'utilisant plus de ressort). Alors oui, écoutez quelqu'un d'autre si vous voulez vraiment résoudre le problème. Si vous voulez juste qu'il disparaisse pour le moment, utilisez cette réponse. C'est une idée terrible, mais diable, pourrait fonctionner pour vous. Pour mémoire, je n'ai plus jamais eu de crash ou de problème après cela. Mais c'est probablement la source de ce qui a fini par être un cauchemar de performances SQL.
la source
"handler":{},"hibernateLazyInitializer":{}
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Comme il est correctement suggéré dans les réponses précédentes, le chargement différé signifie que lorsque vous récupérez votre objet de la base de données, les objets imbriqués ne sont pas récupérés (et peuvent être récupérés plus tard si nécessaire).
Maintenant, Jackson tente de sérialiser l'objet imbriqué (== en faire du JSON), mais échoue car il trouve JavassistLazyInitializer au lieu de l'objet normal. C'est l'erreur que vous voyez. Maintenant, comment le résoudre?
Comme suggéré précédemment par CP510, une option est de supprimer l'erreur par cette ligne de configuration:
Mais cela concerne les symptômes, pas la cause . Pour le résoudre avec élégance, vous devez décider si vous avez besoin de cet objet en JSON ou non?
Si vous avez besoin de l'objet dans JSON, supprimez l'
FetchType.LAZY
option du champ qui le provoque (il peut également s'agir d'un champ dans un objet imbriqué, pas seulement dans l'entité racine que vous récupérez).Si vous n'avez pas besoin de l'objet en JSON, annotez le getter de ce champ (ou le champ lui-même, si vous n'avez pas besoin d'accepter les valeurs entrantes non plus) avec
@JsonIgnore
, par exemple:// this field will not be serialized to/from JSON @JsonIgnore private NestedType secret;
Si vous avez des besoins plus complexes (par exemple des règles différentes pour différents contrôleurs REST utilisant la même entité), vous pouvez utiliser les vues ou le filtrage jackson ou pour un cas d'utilisation très simple, récupérer les objets imbriqués séparément.
la source
RangeError: Maximum call stack size exceeded
Vous pouvez utiliser le module complémentaire pour Jackson qui gère le chargement paresseux d'Hibernate.
Plus d'informations sur https://github.com/FasterXML/jackson-datatype-hibernate qui prend en charge les hibernates 3 et 4 séparément.
la source
Je pense que le problème est la façon dont vous récupérez l'entité.
Peut-être que vous faites quelque chose comme ça:
Essayez d'utiliser la méthode
get
au lieu deload
Le problème est qu'avec la méthode de chargement, vous obtenez juste un proxy mais pas le vrai objet. L'objet proxy n'a pas les propriétés déjà chargées, donc lorsque la sérialisation se produit, il n'y a aucune propriété à sérialiser. Avec la méthode get, vous obtenez réellement l'objet réel, cet objet pourrait en fait être sérialisé.
la source
ça marche pour moi
par exemple
la source
Il existe deux façons de résoudre le problème.
Voie 1 :
Ajouter
spring.jackson.serialization.fail-on-empty-beans=false
dans application.propertiesVoie 2 :
Utilisez
join fetch
dans la requête JPQL pour récupérer les données de l'objet parent, voir ci-dessous:la source
Ajoutez cette annotation à la classe d'entité (modèle) qui fonctionne pour moi, cela provoque un chargement paresseux via l'objet proxy d'hibernation.
la source
Cette exception
obtenir parce que, je l'espère, vous envoyez une sortie de réponse en tant qu'objet sérialisable.
C'est un problème qui se produit au printemps. Pour résoudre ce problème, envoyez un objet POJO comme sortie de réponse.
Exemple :
Classe POJO:
Dans le contrôleur, convertissez les champs d'objet sérialisables en champs de classe POJO et retournez la classe pojo en sortie.
la source
Dans Hibernate 5.2 et supérieur, vous pouvez supprimer le proxy d'hibernation comme ci-dessous, il vous donnera l'objet réel afin que vous puissiez le sérialiser correctement:
la source
Hibernate.initialize
au préalable.Pour Hibernate, vous pouvez utiliser le projet jackson-datatype-hibernate pour gérer la sérialisation / désérialisation JSON avec des objets à chargement différé.
Par exemple,
la source
can't parse JSON. Raw result:
. De l'aide?La solution est inspirée de la solution ci-dessous par @marco. J'ai également mis à jour sa réponse avec ces datails.
Le problème ici concerne le chargement paresseux des sous-objets, où Jackson ne trouve que des proxys d'hibernation, au lieu d'objets complets.
Il nous reste donc deux options: supprimer l'exception, comme ci-dessus dans la réponse la plus votée ici, ou s'assurer que les objets LazyLoad sont chargés.
Si vous choisissez d'utiliser la dernière option, la solution serait d'utiliser la bibliothèque jackson-datatype et de configurer la bibliothèque pour initialiser les dépendances de chargement différé avant la sérialisation.
J'ai ajouté une nouvelle classe de configuration pour ce faire.
}
@Primary
s'assure qu'aucune autre configuration Jackson n'est utilisée pour initialiser d'autres beans.@Bean
est comme d'habitude.module.enable(Hibernate5Module.Feature.FORCE_LAZY_LOADING);
consiste à activer le chargement différé des dépendances.Attention - Veuillez surveiller son impact sur les performances. Parfois, EAGER fetch aide, mais même si vous le rendez impatient, vous aurez toujours besoin de ce code, car les objets proxy existent toujours pour tous les autres mappages sauf
@OneToOne
PS: Comme commentaire général, je découragerais la pratique de renvoyer l'objet de données entier dans la réponse Json. On devrait utiliser des Dto pour cette communication, et utiliser un mappeur comme mapstruct pour les mapper. Cela vous évite les failles de sécurité accidentelles, ainsi que l'exception ci-dessus.
la source
J'ai le même problème en ce moment. vérifiez si vous corrigez la récupération paresseux avec un @jsonIQgnore
Supprimez simplement le "(fetch = ...)" ou l'annotation "@jsonIgnore" et cela fonctionnera
la source
Ou vous pouvez configurer le mappeur comme:
// configuration personnalisée pour le chargement paresseux
et configurez le mappeur:
la source
Cela pourrait être votre relation d'entité Hibernate à l'origine du problème ... arrêtez simplement le chargement paresseux de cette entité associée ... par exemple ... J'ai résolu ci-dessous en définissant lazy = "false" pour customerType.
la source
J'ai changé (dans la classe de modèle Annotation)
à
et a bien fonctionné ...
Aimer.
la source
fetch
stratégie sur un modèle a plusieurs conséquences sur les performances. Avec ce changement, vous apportez beaucoup plus de données de la base de données. Cela peut être une solution valable, mais une étude de performance est d'abord nécessaire.C'est un problème avec Jackson. Pour éviter cela, demandez à Jackson de ne pas sérialiser la relation imbriquée ou la classe imbriquée.
Regardez l'exemple suivant. Classe d' adresses mappée aux classes Ville , État et Pays et l'État lui-même pointe vers Pays et Pays pointant vers Région. Lorsque vous obtenez des valeurs d'adresse via l'API REST Spring Boot, vous obtiendrez l'erreur ci-dessus. Pour éviter cela, sérialisez simplement la classe mappée (qui reflète le JSON de niveau un) et ignorez les relations imbriquées avec
@JsonIgnoreProperties(value = {"state"})
,@JsonIgnoreProperties(value = {"country"})
et@JsonIgnoreProperties(value = {"region"})
Cela empêchera l'exception Lazyload avec l'erreur ci-dessus. Utilisez le code ci-dessous comme exemple et modifiez vos classes de modèle.
Address.java
Ville.java
State.java
Country.java
la source
Essayer
implements interface Serializable
la source