JSON 序列化程序中的延迟加载错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6277439/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 17:52:40  来源:igfitidea点击:

Lazy Loadng error in JSON serializer

jsonhibernatespringspring-mvclazy-loading

提问by danny.lesnik

I have such kind of @OneToOne Hibernate relationShip

我有这种@OneToOne Hibernate 关系

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 Item is mapped as LAZY.

地址项映射为 LAZY。

Now I want to fetch user and it's address using

现在我想获取用户及其地址使用

session.load(Student.class,id);

In my daoService.

在我的 daoService 中。

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

然后我将它作为 JSON 从我的 Spring MVC 控制器返回:

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

Unfortunately, it's not working because of Lazy clasees and I fails with:

不幸的是,由于 Lazy clasees,它不起作用,我失败了:

org.codehaus.Hymanson.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.Hymanson.map.ser.StdSerializerProvider.serialize(StdSerializerProvider.java:62)

I do use OpenSessionInViewInterceptor and it works just fine. I understand that I can user left join HQL query and retrieve student and address that way and solve the problem. I also understand that changing relation to EAGER will solve it.

我确实使用 OpenSessionInViewInterceptor 并且它工作得很好。我知道我可以用户离开加入 HQL 查询并检索学生并通过这种方式解决问题。我也明白改变与 EAGER 的关系将解决它。

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

但是我如何使用标准的 Hymanson 消息转换器序列化到 JSON 惰性类,这是我添加到我的 XML 文件中的原因。

回答by Sean Patrick Floyd

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.

如果这不是您的选择,请确保实体 Object 已分离。

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

使用 JPA (2),您将使用EntityManager.detach(entity),而普通的 Hibernate 等效于Session.evict(entity).

回答by NewBee

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

一旦我编写了一个处理器来处理这个问题,但现在使用Hymanson hibernate 模块很容易解决这个问题。

回答by bhagyas

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

在您的 DAO 方法中添加Hibernate.initialize(<your getter method>);以解决此问题。

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

Try like the above.

像上面一样尝试。

回答by Mite Mitreski

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

还有另一种选择可以解决您的问题。您可以在 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.

问题是实体被延迟加载并且序列化在它们完全加载之前发生。

回答by davidxxx

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

但是我如何使用标准的 Hymanson 消息转换器序列化到 JSON 惰性类,这是我添加到我的 XML 文件中的原因。

First of all, I don't advise to use DTO/Value Object onlyto 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.

首先,我不建议使用 DTO/Value Object来解决此问题。
您可能会发现一开始很容易,但是在每次新的开发/更改中,重复的代码意味着每次都进行两次修改……否则会出现错误。

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.

我并不是说 VO 或 DTO 是不好的味道,但您应该出于它们的设计原因使用它们(例如提供根据逻辑层不同的内容/结构或解决无法解决的序列化问题)。
如果您有一种干净有效的方法来解决没有 VO/DTO 的序列化问题,并且您不需要它们,请不要使用它们。

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

关于它,当您将 Hymanson 与 Hibernate 实体一起使用时,有很多方法可以解决延迟加载问题。

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

实际上,最简单的方法是使用FasterXML/Hymanson-datatype-hibernate

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

构建Hymanson模块(jar)以支持Hibernate(http://hibernate.org)特定数据类型和属性的JSON序列化和反序列化的项目;尤其是延迟加载方面。

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

它提供Hibernate3Module/Hibernate4Module/Hibernate5Module了可以注册的扩展模块,ObjectMapper以提供一组定义良好的与 Hibernate 特性相关的扩展。

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

要使其工作,您只需要添加所需的依赖项并在需要处理的地方添加可用的 Hymanson 模块。

If you use Hibernate 3 :

如果您使用休眠 3:

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

If you use Hibernate 4 :

如果您使用休眠 4:

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

And so for...

所以对于...

Where Hymanson.version.datatypeshould be the same for the used Hymanson version and the ackson-datatype extension.

Hymanson.version.datatype对于使用的 Hymanson 版本和 ackson-datatype 扩展,哪里应该是相同的。

If you use or may use Spring Boot, you just need to declare the module as a bean in a specific Configurationclass or in the SpringBootApplicationclass and it will be automatically registered for any Hymanson ObjectMappercreated.

如果您使用或可能使用 Spring Boot,您只需要在特定Configuration类或SpringBootApplication类中将模块声明为 bean,它将自动为任何 HymansonObjectMapper创建。

The 74.3 Customize the Hymanson ObjectMapperSpring Boot section states that :

74.3 Customize the Hymanson ObjectMapper春季引导部分指出:

Any beans of type com.fasterxml.Hymanson.databind.Modulewill be automatically registered with the auto-configured Hymanson2ObjectMapperBuilderand applied to any ObjectMapperinstances that it creates. This provides a global mechanism for contributing custom modules when you add new features to your application.

任何类型的 beancom.fasterxml.Hymanson.databind.Module将自动注册到自动配置 Hymanson2ObjectMapperBuilder并应用于ObjectMapper它创建的任何实例。当您向应用程序添加新功能时,这提供了用于贡献自定义模块的全局机制。

For example :

例如 :

@Configuration
public class MyHymansonConfig {

    @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();
    }
}