Lazy Loadng error in JSON serializer

I have such an attitude @OneToOne Hibernate attitude

public class Address implements Serializable { private String id; private String city; private String country; //setter getters ommitted } public class Student implements Serializable { private String id; private String firstName; private String lastName; private Address address; } 

Address The item is displayed as LAZY.

Now I want to get the user and his address using

 session.load(Student.class,id); 

In my daoService.

Then I return it as JSON from my Spring MVC controller:

 @RequestMapping(value="/getStudent.do",method=RequestMethod.POST) @ResponseBody public Student getStudent(@RequestParam("studentId") String id){ Student student = daoService.getStudent(id); return student; } 

Unfortunately, it does not work due to Lazy clasees, and I fail:

 org.codehaus.jackson.map.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.vanilla.objects.Student_$$_javassist_1["address"]->com.vanilla.objects.Address_$$_javassist_0["handler"]) at org.codehaus.jackson.map.ser.StdSerializerProvider$1.serialize(StdSerializerProvider.java:62) 

I am using OpenSessionInViewInterceptor and it works fine. I understand that I can leave the user in the HQL query and restore it and solve this problem. I also understand that changing attitudes towards EAGER will solve it.

But how can I serialize lazy classes into JSON using the standard Jackson message converter, which due to reasons I added to my XML file.

+4
source share
5 answers

The simplest solution: do not serialize entities, use Value objects.

If this is not an option for you, make sure that the object object is detached.

With JPA (2), you would use EntityManager.detach(entity) , with a simple Hibernate equivalent to Session.evict(entity) .

+6
source

As soon as I write a processor to handle this, it is now easy to fix it using the jackson sleep module .

+5
source

Within the DAO method, add Hibernate.initialize(<your getter method>); , to solve this problem.

 Student student = findById(<yourId>); Hibernate.initialize(student.getAddress()); ... return student; 

Try to do it higher.

+4
source

There is another option that solves your problems. You can add this filter in web.xml

 <filter> <filter-name>springOpenEntityManagerInViewFilter</filter-name> <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> <init-param> <param-name>entityManagerFactoryBeanName</param-name> <param-value>entityManagerFactory</param-value> </init-param> </filter> <filter-mapping> <filter-name>springOpenEntityManagerInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 

The problem is that objects are loading lazy and serialization happens before they are fully loaded.

0
source

But how can I serialize lazy classes into JSON using the standard jackson that I added to my XML file.

First of all, I do not recommend using the DTO / Value Object just to solve this problem.
You can easily find this at the beginning, but with each new development / change, duplicate code means to make all the changes twice ... otherwise, errors.

I do not mean that VO or DTO are bad smells, but you should use them for the reasons they are designed (for example, providing a content / structure that differs according to logical levels or solving an unsolvable serialization problem).
If you have a clean and efficient way to solve the serialization problem without VO / DTO, and you don't need them, don't use them.

And about that, there are many ways to solve the lazy loading problem as you are using Jackson with Hibernate objects.

In fact, the easiest way is to use FasterXML / jackson-datatype-hibernate

Jackson (jar) module project to support JSON serialization and Hibernate deserialization ( http://hibernate.org ) data types and properties; especially lazy aspects.

It provides Hibernate3Module/Hibernate4Module/Hibernate5Module , extension modules that can be registered with ObjectMapper to provide a well-defined set of extensions related to the Hibernate specifications.

To do this, you just need to add the required dependency and add the Jackson module is available during processes where necessary.

If you are using Hibernate 3:

  <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-hibernate3</artifactId> <version>${jackson.version.datatype}</version> </dependency> 

If you are using Hibernate 4:

  <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-hibernate4</artifactId> <version>${jackson.version.datatype}</version> </dependency> 

And so for ...

Where jackson.version.datatype should be the same for the version of Jackson used and the ackon-datatype extension.

If you use or can use Spring Boot, you just need to declare the module as a bean in a specific Configuration class or in a SpringBootApplication class, and it will be automatically registered for any Jackson ObjectMapper .

74.3 Customize the Jackson ObjectMapper Spring The download section states that:

Any beans of the type com.fasterxml.jackson.databind.Module will be automatically registered using the automatic Jackson2ObjectMapperBuilder configuration and applied to any ObjectMapper instances that it creates. This provides a global mechanism for facilitating custom modules when adding new features to your application.

For instance:

 @Configuration public class MyJacksonConfig { @Bean public Module hibernate5Module() { return new Hibernate5Module(); } } 

or:

 @SpringBootApplication public class AppConfig { public static void main(String[] args) throws IOException { SpringApplication.run(AppConfig.class, args); } @Bean public Module hibernate5Module() { return new Hibernate5Module(); } } 
0
source

All Articles