Éviter Jackson sérialisation non récupérés paresseux objets
J'ai un contrôleur simple que de retourner un objet Utilisateur, cet utilisateur ont un attribut de coordonnées qui ont la propriété hibernate FetchType.PARESSEUX.
Lorsque j'essaie d'obtenir de cet utilisateur, je l'ai toujours à la charge de toutes les coordonnées pour obtenir de l'utilisateur de l'objet, sinon quand Jackson essayez de sérialiser l'Utilisateur lance l'exception:
com.fasterxml.jackson.databind.JsonMappingException: impossible d'initialiser le proxy - pas de Session
Cela est dû à Jackson essaie de récupérer ce unfetched objet. Voici les objets:
public class User{
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
@JsonManagedReference("user-coordinate")
private List<Coordinate> coordinates;
}
public class Coordinate {
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
@JsonBackReference("user-coordinate")
private User user;
}
Et le contrôleur:
@RequestMapping(value = "/user/{username}", method=RequestMethod.GET)
public @ResponseBody User getUser(@PathVariable String username) {
User user = userService.getUser(username);
return user;
}
Il y a une manière de dire à Jackson pour ne pas arranger le unfetched objets? J'ai été à la recherche d'autres réponses posté il y a 3 ans la mise en œuvre de jackson-hibernate-module. Mais probablement il pourrait être réalisé avec un nouveau jackson fonctionnalité.
Mes versions sont:
- Printemps 3.2.5
- Hibernate 4.1.7
- Jackson 2.2
Merci d'avance.
- l'approche décrite dans ces 2 liens a fonctionné pour moi, Printemps 3.1, Hibernate 4 et Jackson-Module-Hibernate et FasterXML / jackson-type de données-hibernate
- Merci indybee, j'ai regardé le tutoriel, printemps 3.2.5 ont déjà un MappingJackson2HttpMessageConverter, mais je ne peux pas l'utiliser afin d'éviter la non récupérés paresseux objet, aussi j'ai essayé de la mise en œuvre de l'un dans le tutoriel, mais rien...
- êtes-vous d'obtenir le même message d'erreur "impossible d'initialiser le proxy" ou quelque chose de différent? (j'ai utilisé le supplément de HibernateAwareObjectMapper décrites dans les articles avec le Printemps 3.2.6 et Hibernate 4.1.7 et jackson 2.3)
- Je l'ai!! Depuis la version 3.1.2 de Printemps ont son propre MappingJackson2HttpMessageConverter et ont presque le même comportement que celui du tutoriel, mais le problème est que je suis en utilisant Spring java config et je commence avec javaconfigs. J'essayais de faire un @Bean MappingJackson2HttpMessageConverter, au lieu de l'ajouter à la HttpMessageConverters de Printemps, c'est peut-être plus clair dans la réponse 🙂
- content que ça fonctionne 🙂
- Est-il cassé au Printemps Boot 2?
Vous devez vous connecter pour publier un commentaire.
J'ai enfin trouvé la solution! grâce à indybee pour me donner une idée.
Le tutoriel Printemps 3.1, Hibernate 4 et Jackson-Module-Hibernate une bonne solution pour le Printemps 3.1 et versions antérieures. Mais depuis la version 3.1.2 de Printemps ont son propre MappingJackson2HttpMessageConverter avec presque les mêmes fonctionnalités que celui du tutoriel, nous n'avons pas besoin de créer cette coutume HTTPMessageConverter.
Avec javaconfig nous n'avons pas besoin de créer un HibernateAwareObjectMapper trop, nous avons juste besoin d'ajouter le Hibernate4Module à la valeur par défaut MappingJackson2HttpMessageConverter que le Printemps et l'ajouter à la HttpMessageConverters de l'application, nous avons donc besoin de:
Étendre notre printemps config classe de WebMvcConfigurerAdapter et remplacer la méthode configureMessageConverters.
Sur la méthode ajouter le MappingJackson2HttpMessageConverter avec le Hibernate4Module inscrit dans un previus méthode.
Notre config de classe devrait ressembler à ceci:
Si vous avez un fichier xml de configuration, vous n'avez pas besoin de créer votre propre MappingJackson2HttpMessageConverter soit, mais vous avez besoin de créer l'personnalisé mappeur qui apparaît dans le tutoriel (HibernateAwareObjectMapper), de sorte que votre configuration xml devrait ressembler à ceci:
Espère que cette réponse soit compréhensible et aider quelqu'un à trouver la solution à ce problème, des questions n'hésitez pas à demander!
Dès le Printemps 4.2 et à l'aide de Printemps de Démarrage et javaconfig, l'enregistrement de la Hibernate4Module est maintenant aussi simple que d'ajouter ceci à votre configuration:
ref: https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring
Hibernate5Module
. Elle a en outre besoin d'une dépendance à<groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-hibernate5</artifactId>
Ceci est similaire à la solution retenue par @rick.
Si vous ne voulez pas toucher message existant convertisseurs de configuration, vous pouvez simplement déclarer un
Jackson2ObjectMapperBuilder
bean comme:Ne pas oublier d'ajouter la dépendance suivant à votre Gradle fichier (ou Maven):
Utile si vous avez un spring-boot de l'application et que vous souhaitez garder la possibilité de modifier Jackson caractéristiques de
application.properties
fichier.application.properties
fichier?Dans le cas de Données du Printemps de Repos, alors que la solution posté par @r1ckr œuvres, tout ce qui est nécessaire est d'ajouter l'une des dépendances suivantes, selon votre version d'Hibernate:
ou
Dans les Données du Printemps Reste il y a une classe:
org.springframework.data.rest.webmvc.json.Jackson2DatatypeHelper
qui s'auto-détecter et enregistrer le Module sur l'application start-up.
Il y a cependant un problème:
Problème De Sérialisation Paresseux @ManyToOne
Si vous utilisez XML de configuration et d'utilisation
<annotation-driven />
, j'ai trouvé que vous avez à nid<message-converters>
à l'intérieur de<annotation-driven>
comme recommandé sur le Jackson compte Github.Comme suit:
`
Pour ceux qui sont venus ici à la recherche à trouver la solution pour Apache CXF RESTful service, la configuration qu'il fixe est ci-dessous:
Où HibernateAwareObjectMapper est défini comme:
La dépendance suivant est requis en juin 2016 (si vous vous trouvez à l'aide de Hibernate5):
La solution suivante est pour le Printemps 4.3, (non-démarrage) & Hibernate 5.1 où nous avons passé tous les fetchtypes à
fetch=FetchType.LAZY
de cas defetch=FetchType.EAGER
pour des raisons de performances. Immédiatement, nous avons vu lacom.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy
exception en raison de la charge paresseux question.Tout d'abord, on ajoute ce qui suit maven dependency:
Puis le suivant est ajouté à notre Java MVC fichier de configuration:
Notes:
Vous avez besoin pour créer et configurer la Hibernate5Module pour obtenir un comportement similaire à Jackson sans ce module. La valeur par défaut rend incompatible hypothèses.
Notre
WebMvcConfigurerAdapter
a beaucoup d'autres configuration et nous voulions éviter une autre configuration de la classe, c'est pourquoi nous n'avons pas utilisé laWebMvcConfigurationSupport#addDefaultHttpMessageConverters
fonction qui a été évoqué sur d'autres postes.WebMvcConfigurerAdapter#configureMessageConverters
désactive tous de Printemps de la configuration interne de message convertisseurs. Nous avons préféré éviter les problèmes potentiels autour de ce.À l'aide de
extendMessageConverters
activé l'accès à tous les automatiquement configuré Jackson classes sans perdre la configuration de tous les autres message convertisseurs.À l'aide de
getObjectMapper#registerModule
nous avons été en mesure d'ajouter leHibernate5Module
existant pour les convertisseurs.Cet ajout a résolu le problème avec Hibernate et le chargement paresseux, mais a entraîné une résiduelle problème avec le format JSON généré. Comme indiqué dans cette question github, la mise en veille prolongée-jackson lazy load module actuellement ignore l' @JsonUnwrapped annotation, menant à d'éventuelles erreurs de données. Cela se produit indépendamment de la force de chargement de paramètre de fonction. Le problème a été là depuis de 2016.
Note
Il semble que, par adjonction, à des classes qui sont paresseux-chargé, le haut-ObjectMapper fonctionne sans l'ajout de la hibernate5 module:
Vous pouvez utiliser l'aide de Données du Printemps de Repos projet:
J'ai essayé @rick réponse utile, mais a couru dans le problème que "bien connus des modules" comme jackson-type de données-jsr310 n'étaient pas automatiquement inscrits malgré eux d'être dans le classpath. (Ce post de blog explique l'auto-enregistrement.)
Expansion sur @la réponse de rick, voici une variation à l'aide du Printemps Jackson2ObjectMapperBuilder pour créer le
ObjectMapper
. Cette auto-inscrit le "bien connu des modules" et définit certaines caractéristiques, en plus de l'installation de laHibernate4Module
.hibernate5Module
(parce que im en utilisant hibernate 5), jackson ignore le proxy de non initialisé objets, mais il semble que le "bien connu des modules" ne sont pas enregistrés en dépit je utiliser votre approche. Je ne le sais parce que certaines parties de mon application sont brisés, et quand j'ai enlever le Module, ils fonctionnent de nouveau.DelegatingWebMvcConfiguration
classe (au lieu deWebMvcConfigurerAdapter
) comme suggéré par le Jackson-Antpath-Filtre:@Override public void configureMessageConverters(List<HttpMessageConverter<?>> messageConverters) { messageConverters.add(jacksonMessageConverter()); addDefaultHttpMessageConverters(messageConverters); }
Bien que cette question est un peu différent de celui-ci : Étrange Jackson exception levée lors de la sérialisation d'Hibernate objet, le problème peut être résolu de la même manière avec ce code:
J'ai essayé cela, et a travaillé:
//configuration personnalisée pour le chargement paresseux
et configurer mappeur:
J'ai fait une solution très simple à ce problème.
Dans mon cas, j'ai été donner de l'erreur, car à chaque fois que je revenais d'un pendencies, comme une bonne pratique que je me suis converti à une liste qui ne peut pas être modifié, mais la façon dont il pourrait ou pourrait ne pas être paresseux en fonction de la méthode que j'ai utilisé pour obtenir de l'instance (avec ou sans extraction), je fais un test avant il a été initialisée par Hibernate et ajouter l'annotation qui empêche la sérialisation d'un vide de la propriété et qui a résolu mon problème.