Lazy Loadng error in JSON serializer

自闭症网瘾萝莉.ら 提交于 2019-11-29 14:31:36

The easiest solution: Don't serialize entities, use Value Objects.

If that is not an option for you, make sure that the entity Object is detached.

With JPA (2), you would use EntityManager.detach(entity), with plain Hibernate the equivalent is Session.evict(entity).

NewBee

Once I write a processor to handle this but now it's easy to fix this by using the jackson hibernate module.

Within your DAO method add Hibernate.initialize(<your getter method>); to resolve this.

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

Try like the above.

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 entities are loaded lazy and serialization happens before they get loaded fully.

But how can I serialize to JSON lazy classes using standard jackson message converter which of cause I added to my XML file.

First of all, I don't advise to use DTO/Value Object only to solve this issue.
You may find it easy at the beginning but at each new development/change, the duplicate code means making twice modifications at each time... otherwise bugs.

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

And about it, there is many ways to solve lazy loading issue as you use Jackson with Hibernate entities.

Actually, the simplest way is using FasterXML/jackson-datatype-hibernate

Project to build Jackson module (jar) to support JSON serialization and deserialization of Hibernate (http://hibernate.org) specific datatypes and properties; especially lazy-loading aspects.

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

To do it working, you just need to add the required dependency and to add the Jackson Module available during processings where it is required.

If you use Hibernate 3 :

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

If you use 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 used Jackson version and the ackson-datatype extension.

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

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

Any beans of type com.fasterxml.jackson.databind.Module will be automatically registered with the auto-configured Jackson2ObjectMapperBuilder and applied to any ObjectMapper instances that it creates. This provides a global mechanism for contributing custom modules when you add new features to your application.

For example :

@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();
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!