没有为类org.hibernate.proxy.pojo.javassist.Javassist找到序列化器?

时间:2021-06-21 16:35:01

I am working on SpringMVC, Hibernate & JSON but I am getting this error.

我正在开发SpringMVC、Hibernate和JSON,但是我得到了这个错误。

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) ) 

Please check my Entity below

请在下面检查我的实体

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

    }

How can I Solve this?

我怎么解决这个问题?

9 个解决方案

#1


91  

I had a similar problem with lazy loading via the hibernate proxy object. Got around it by annotating the class having lazy loaded private properties with:

通过hibernate代理对象延迟加载也有类似的问题。通过注释具有惰性加载的私有属性的类来绕过它:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

I assume you can add the properties on your proxy object that breaks the JSON serialization to that annotation.

我假设您可以在代理对象上添加属性,该属性将JSON序列化中断到该注释。

The problem is that entities are loaded lazily and serialization happens before they get loaded fully.

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

Hibernate.initialize(<your getter method>);

#2


40  

Just to add this in, I ran into this same issue, but the supplied answers did not work. I fixed it by taking the exception's suggestion and adding to the application.properties file...

为了补充这一点,我遇到了同样的问题,但是提供的答案没有起作用。我通过采纳异常的建议并添加到应用程序中来修复它。属性文件…

spring.jackson.serialization.fail-on-empty-beans=false

I'm using Spring Boot v1.3 with Hibernate 4.3

我正在使用Spring Boot v1.3和Hibernate 4.3

It now serializes the entire object and nested objects.

它现在序列化整个对象和嵌套对象。

#3


35  

As it is correctly suggested in previous answers, lazy loading means that when you fetch your object from the database, the nested objects are not fetched (and may be fetched later when required).

正如在前面的回答中正确建议的那样,延迟加载意味着当您从数据库中获取对象时,嵌套对象不会被获取(在需要的时候可能会被获取)。

Now Jackson tries to serialize the nested object (== make JSON out of it), but fails as it finds JavassistLazyInitializer instead of normal object. This is the error you see. Now, how to solve it?

现在,Jackson试图序列化嵌套对象(== make JSON out of it),但是当它找到JavassistLazyInitializer而不是普通对象时失败了。这就是你看到的错误。现在,如何解决它呢?

As suggested by CP510 previously, one option is to suppress the error by this line of configuration:

正如前面CP510所建议的,一个选项是通过以下配置行来抑制错误:

spring.jackson.serialization.fail-on-empty-beans=false

But this is dealing with the symptoms, not the cause. To solve it elegantly, you need to decide whether you need this object in JSON or not?

但这是针对症状,而不是病因。要优雅地解决这个问题,您需要决定是否需要JSON格式的对象?

  1. Should you need the object in JSON, remove the FetchType.LAZY option from the field that causes it (it might also be a field in some nested object, not only in the root entity you are fetching).

    如果需要JSON中的对象,请删除FetchType。来自导致它的字段的懒惰选项(它也可能是某个嵌套对象中的字段,而不只是在您正在获取的根实体中)。

  2. If do not need the object in JSON, annotate the getter of this field (or the field itself, if you do not need to accept incoming values either) with @JsonIgnore, for example:

    如果不需要JSON中的对象,可以使用@JsonIgnore注释该字段的getter(或者字段本身,如果您也不需要接受传入值),例如:

    // this field will not be serialized to/from JSON @JsonIgnore private NestedType secret;

    //此字段不会被序列化为/from JSON @JsonIgnore private NestedType secret;

Should you have more complex needs (e.g. different rules for different REST controllers using the same entity), you can use jackson views or filtering or for very simple use case, fetch nested objects separately.

如果您有更复杂的需求(例如使用相同实体的不同REST控制器的不同规则),您可以使用jackson视图或过滤,或者对于非常简单的用例,分别获取嵌套对象。

#4


12  

I think that the problem is the way that you retrieve the entity.

我认为问题在于你检索实体的方式。

Maybe you are doing something like this:

也许你正在做这样的事情:

Person p = (Person) session.load(Person.class, new Integer(id));

Try using the method get instead of load

试着用get代替load。

Person p = (Person) session.get(Person.class, new Integer(id));

The problem is that with load method you get just a proxy but not the real object. The proxy object doesn't have the properties already loaded so when the serialization happens there are no properties to be serialized. With the get method you actually get the real object, this object could in fact be serialized.

问题是使用load方法只能得到一个代理,而不能得到真正的对象。代理对象没有已经加载的属性,所以当序列化发生时,没有属性需要序列化。通过get方法,你实际上得到了真实的对象,这个对象实际上可以被序列化。

#5


5  

You could use the add-on module for Jackson which handles Hibernate lazy-loading.

您可以使用Jackson的附加模块来处理Hibernate延迟加载。

More info on https://github.com/FasterXML/jackson-datatype-hibernate wich support hibernate 3 and 4 separately.

关于https://github.com/FasterXML/jackson-datatype-hibernate的更多信息分别支持hibernate 3和4。

#6


0  

Try

试一试

implements interface Serializable

实现Serializable接口

#7


0  

Or you could configure mapper as :

或者您可以将mapper配置为:

// custom configuration for lazy loading

//延迟加载的自定义配置

public static class HibernateLazyInitializerSerializer extends JsonSerializer<JavassistLazyInitializer> {

    @Override
    public void serialize(JavassistLazyInitializer initializer, JsonGenerator jsonGenerator,
            SerializerProvider serializerProvider)
            throws IOException, JsonProcessingException {
        jsonGenerator.writeNull();
    }
}

and configure mapper:

和配置映射器:

    mapper = new JacksonMapper();
    SimpleModule simpleModule = new SimpleModule(
            "SimpleModule", new Version(1,0,0,null)
    );
    simpleModule.addSerializer(
            JavassistLazyInitializer.class,
            new HibernateLazyInitializerSerializer()
    );
    mapper.registerModule(simpleModule);

#8


0  

It could be your Hibernate entity relationship causing the issue...simply stop lazy loading of that related entity...for example...I resolved below by setting lazy="false" for customerType.

可能是您的Hibernate实体关系导致了问题……只需停止相关实体的延迟加载……例如……下面我通过为customerType设置lazy="false"解决了这个问题。

<class name="Customer" table="CUSTOMER">
        <id name="custId" type="long">
            <column name="CUSTID" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="phone" type="java.lang.String">
            <column name="PHONE" />
        </property>
        <property name="pan" type="java.lang.String">
            <column name="PAN" />
        </property>

        <many-to-one name="customerType" not-null="true" lazy="false"></many-to-one>
    </class>
</hibernate-mapping>

#9


0  

This Exception

这个异常

org.springframework.http.converter.HttpMessageNotWritableException

org.springframework.http.converter.HttpMessageNotWritableException

getting because, I hope so, your are sending response output as Serializable object.
This is problem occurring in spring. To over come this issue, send POJO object as response output.

因为,我希望如此,您将响应输出发送为Serializable对象。这是春季出现的问题。要解决这个问题,发送POJO对象作为响应输出。

Example :

例子:

    @Entity
    @Table(name="user_details")
    public class User implements Serializable{

        @Id
        @GeneratedValue(strategy= GenerationType.IDENTITY)
        @Column(name="id")
        private Integer id;

        @Column(name="user_name")
        private String userName;

        @Column(name="email_id")
        private String emailId;

        @Column(name="phone_no")
        private String phone;

//setter and getters

POJO class:

POJO类:

public class UserVO {

    private int Id;
    private String userName;
    private String emailId;
    private String phone;
    private Integer active;

//setter and getters

In controller convert the serilizable object fields to POJO class fields and return pojo class as output.

在控制器中,将可serilizable对象字段转换为POJO类字段,并返回POJO类作为输出。

         User u= userService.getdetials(); // get data from database

        UserVO userVo= new UserVO();  // created pojo class object

        userVo.setId(u.getId());
        userVo.setEmailId(u.getEmailId());
        userVo.setActive(u.getActive());
        userVo.setPhone(u.getPhone());
        userVo.setUserName(u.getUserName());
       retunr userVo;  //finally send pojo object as output.

#1


91  

I had a similar problem with lazy loading via the hibernate proxy object. Got around it by annotating the class having lazy loaded private properties with:

通过hibernate代理对象延迟加载也有类似的问题。通过注释具有惰性加载的私有属性的类来绕过它:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

I assume you can add the properties on your proxy object that breaks the JSON serialization to that annotation.

我假设您可以在代理对象上添加属性,该属性将JSON序列化中断到该注释。

The problem is that entities are loaded lazily and serialization happens before they get loaded fully.

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

Hibernate.initialize(<your getter method>);

#2


40  

Just to add this in, I ran into this same issue, but the supplied answers did not work. I fixed it by taking the exception's suggestion and adding to the application.properties file...

为了补充这一点,我遇到了同样的问题,但是提供的答案没有起作用。我通过采纳异常的建议并添加到应用程序中来修复它。属性文件…

spring.jackson.serialization.fail-on-empty-beans=false

I'm using Spring Boot v1.3 with Hibernate 4.3

我正在使用Spring Boot v1.3和Hibernate 4.3

It now serializes the entire object and nested objects.

它现在序列化整个对象和嵌套对象。

#3


35  

As it is correctly suggested in previous answers, lazy loading means that when you fetch your object from the database, the nested objects are not fetched (and may be fetched later when required).

正如在前面的回答中正确建议的那样,延迟加载意味着当您从数据库中获取对象时,嵌套对象不会被获取(在需要的时候可能会被获取)。

Now Jackson tries to serialize the nested object (== make JSON out of it), but fails as it finds JavassistLazyInitializer instead of normal object. This is the error you see. Now, how to solve it?

现在,Jackson试图序列化嵌套对象(== make JSON out of it),但是当它找到JavassistLazyInitializer而不是普通对象时失败了。这就是你看到的错误。现在,如何解决它呢?

As suggested by CP510 previously, one option is to suppress the error by this line of configuration:

正如前面CP510所建议的,一个选项是通过以下配置行来抑制错误:

spring.jackson.serialization.fail-on-empty-beans=false

But this is dealing with the symptoms, not the cause. To solve it elegantly, you need to decide whether you need this object in JSON or not?

但这是针对症状,而不是病因。要优雅地解决这个问题,您需要决定是否需要JSON格式的对象?

  1. Should you need the object in JSON, remove the FetchType.LAZY option from the field that causes it (it might also be a field in some nested object, not only in the root entity you are fetching).

    如果需要JSON中的对象,请删除FetchType。来自导致它的字段的懒惰选项(它也可能是某个嵌套对象中的字段,而不只是在您正在获取的根实体中)。

  2. If do not need the object in JSON, annotate the getter of this field (or the field itself, if you do not need to accept incoming values either) with @JsonIgnore, for example:

    如果不需要JSON中的对象,可以使用@JsonIgnore注释该字段的getter(或者字段本身,如果您也不需要接受传入值),例如:

    // this field will not be serialized to/from JSON @JsonIgnore private NestedType secret;

    //此字段不会被序列化为/from JSON @JsonIgnore private NestedType secret;

Should you have more complex needs (e.g. different rules for different REST controllers using the same entity), you can use jackson views or filtering or for very simple use case, fetch nested objects separately.

如果您有更复杂的需求(例如使用相同实体的不同REST控制器的不同规则),您可以使用jackson视图或过滤,或者对于非常简单的用例,分别获取嵌套对象。

#4


12  

I think that the problem is the way that you retrieve the entity.

我认为问题在于你检索实体的方式。

Maybe you are doing something like this:

也许你正在做这样的事情:

Person p = (Person) session.load(Person.class, new Integer(id));

Try using the method get instead of load

试着用get代替load。

Person p = (Person) session.get(Person.class, new Integer(id));

The problem is that with load method you get just a proxy but not the real object. The proxy object doesn't have the properties already loaded so when the serialization happens there are no properties to be serialized. With the get method you actually get the real object, this object could in fact be serialized.

问题是使用load方法只能得到一个代理,而不能得到真正的对象。代理对象没有已经加载的属性,所以当序列化发生时,没有属性需要序列化。通过get方法,你实际上得到了真实的对象,这个对象实际上可以被序列化。

#5


5  

You could use the add-on module for Jackson which handles Hibernate lazy-loading.

您可以使用Jackson的附加模块来处理Hibernate延迟加载。

More info on https://github.com/FasterXML/jackson-datatype-hibernate wich support hibernate 3 and 4 separately.

关于https://github.com/FasterXML/jackson-datatype-hibernate的更多信息分别支持hibernate 3和4。

#6


0  

Try

试一试

implements interface Serializable

实现Serializable接口

#7


0  

Or you could configure mapper as :

或者您可以将mapper配置为:

// custom configuration for lazy loading

//延迟加载的自定义配置

public static class HibernateLazyInitializerSerializer extends JsonSerializer<JavassistLazyInitializer> {

    @Override
    public void serialize(JavassistLazyInitializer initializer, JsonGenerator jsonGenerator,
            SerializerProvider serializerProvider)
            throws IOException, JsonProcessingException {
        jsonGenerator.writeNull();
    }
}

and configure mapper:

和配置映射器:

    mapper = new JacksonMapper();
    SimpleModule simpleModule = new SimpleModule(
            "SimpleModule", new Version(1,0,0,null)
    );
    simpleModule.addSerializer(
            JavassistLazyInitializer.class,
            new HibernateLazyInitializerSerializer()
    );
    mapper.registerModule(simpleModule);

#8


0  

It could be your Hibernate entity relationship causing the issue...simply stop lazy loading of that related entity...for example...I resolved below by setting lazy="false" for customerType.

可能是您的Hibernate实体关系导致了问题……只需停止相关实体的延迟加载……例如……下面我通过为customerType设置lazy="false"解决了这个问题。

<class name="Customer" table="CUSTOMER">
        <id name="custId" type="long">
            <column name="CUSTID" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="phone" type="java.lang.String">
            <column name="PHONE" />
        </property>
        <property name="pan" type="java.lang.String">
            <column name="PAN" />
        </property>

        <many-to-one name="customerType" not-null="true" lazy="false"></many-to-one>
    </class>
</hibernate-mapping>

#9


0  

This Exception

这个异常

org.springframework.http.converter.HttpMessageNotWritableException

org.springframework.http.converter.HttpMessageNotWritableException

getting because, I hope so, your are sending response output as Serializable object.
This is problem occurring in spring. To over come this issue, send POJO object as response output.

因为,我希望如此,您将响应输出发送为Serializable对象。这是春季出现的问题。要解决这个问题,发送POJO对象作为响应输出。

Example :

例子:

    @Entity
    @Table(name="user_details")
    public class User implements Serializable{

        @Id
        @GeneratedValue(strategy= GenerationType.IDENTITY)
        @Column(name="id")
        private Integer id;

        @Column(name="user_name")
        private String userName;

        @Column(name="email_id")
        private String emailId;

        @Column(name="phone_no")
        private String phone;

//setter and getters

POJO class:

POJO类:

public class UserVO {

    private int Id;
    private String userName;
    private String emailId;
    private String phone;
    private Integer active;

//setter and getters

In controller convert the serilizable object fields to POJO class fields and return pojo class as output.

在控制器中,将可serilizable对象字段转换为POJO类字段,并返回POJO类作为输出。

         User u= userService.getdetials(); // get data from database

        UserVO userVo= new UserVO();  // created pojo class object

        userVo.setId(u.getId());
        userVo.setEmailId(u.getEmailId());
        userVo.setActive(u.getActive());
        userVo.setPhone(u.getPhone());
        userVo.setUserName(u.getUserName());
       retunr userVo;  //finally send pojo object as output.