将Hibernate对象序列化为JSON时抛出异常

9

我正在使用Hibernate来加载一个小型数据库到一些代表表格的类中,并与数据库进行交互。一切都很好,我真的可以看到所有结果...而且我没有任何空字段,它们都被使用了。

这里我展示了“主”类(表)。

    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;

    import org.codehaus.jackson.annotate.JsonAutoDetect;
    import org.codehaus.jackson.annotate.JsonProperty;

    @JsonAutoDetect
    public class Advertisement {

      @Id
      @GeneratedValue(strategy=GenerationType.AUTO)
      public int id;
      public SessionT session;
      public int idRoom;
      public String image;

      public Advertisement() {

      }

      /* Getters and Setters */
      @JsonProperty
      public int getID() /* Get example */ {
          return this.id;
      }
    }

并且

    @JsonAutoDetect
    public class SessionT {

      @Id
      @GeneratedValue(strategy=GenerationType.AUTO)
      public int id;
      public int iStatus;
      public String sStatus;
      public Date dtDateStart;
      public Date dtDateEnd;
      public boolean bhide;

      /* Constructor, Getter and Setters*/
    }

我的目标是从广告的列表中生成JSON并通过Http发送。
ObjectMapper mapper = new ObjectMapper();System.out.println("mapper started!");
mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
response.getOutputStream().println(mapper.writeValueAsString(ads));

因为某些原因,我遇到了以下错误:

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: java.util.ArrayList[0]->entities.slave.Advertisement["session"]->entities.slave.SessionT_$$_javassist_2["hibernateLazyInitializer"])

我正在使用jackson-all-1.9.11和JBoss Studios 6.01。有人能帮助我吗?
4个回答

24

你能试一试吗?

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

或者一个相对简单的方法是手动在每个getter上使用@JsonProperty进行注释。


已经手动在每个getter上加了@JsonProperty的注解... 我会尝试使用@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})。 - Fernando Carvalho
是的,我认为这个错误是因为Jackson在对象完全加载之前尝试进行序列化。看起来Advertisement和SessionT是延迟加载的,也就是说,在JSON序列化开始时它们还没有被加载。如果这样解决了问题,请告诉我。这很有趣。 - Ankit
1
这在某些情况下可以正常工作,当延迟加载的集合已经从数据库中获取时,但在其他情况下(异常、缺失数据等)很可能会产生意外的结果。你的情况可能有所不同,但我建议你查看我的回答中提到的jackson-datatype-hibernate模块(并升级你的Jackson版本,因为它们从CodeHaus移动到了FasterXML以获得新版本)。 - Christophe L
1
这对我有效,但请注意,如果您正在使用PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy(),则注释应为:@JsonIgnoreProperties({"hibernate_lazy_initializer","handler"}) - mmeyer

3
如果您有一个实体与另一个实体相关联,Hibernate会用所谓的持久性包(Persistence Bag)替换列表或引用类。这使得一些延迟加载成为可能。我认为这是通过您的会话属性发生的。如果我没错的话,在从数据库加载广告后,您应该能在调试器中看到它。
我不知道Json序列化程序如何处理这种hibernate魔法。也许您需要将实体复制到pojo dto(一个没有任何Hibernate上下文的类)中,然后将该dto序列化为json...但也许还有更好的方法。您可以尝试停用延迟加载,但我不确定这是否真正改变了Hibernate的行为...

你在调试器中看到 session 值的类型了吗?它是否与 SessionT 不同?如果不是,那么我的想法是错误的;-) - treeno
1
对我来说,我必须将FetchType.LAZY更改为FetchType.EAGER。 - Jawad Khan

2
当Hibernate从数据库加载对象时,它返回代理对象,这些对象看起来像您的Advertisment或SessionT,但其中包含更多“内容”(以处理它们与会话的关系,延迟加载集合的内部状态等)。
这会使Jackson序列化程序失效,因为它依赖于内省来查找对象的属性。
有一个项目可以使Jackson与Hibernate实体一起使用。请参见:https://github.com/FasterXML/jackson-datatype-hibernate

现在有了你的帮助,我明白了这个版本的jackson在项目中可能会产生什么影响。我一开始尝试使用上面的例子,但它不起作用。所以现在我可以做更多的事情...而且我的代码中真的很少用到jackson,显然随着复杂度的增加,jackson也会增加...但在这个阶段,我肯定会得到帮助(更多的程序员)...目前我是一个人,这件事必须正常工作!感谢你对我的耐心! - Fernando Carvalho

1
如上所述,使用Hibernate模块:https://github.com/FasterXML/jackson-datatype-hibernate,否则Jackson无法知道如何处理特定于第三方库的类型。另外,Jackson 2.x对这些外部类型有更好的支持,因此如果可能的话,使用带有Hibernate模块的Jackson 2.2将是更优选的选择。但我理解升级并不总是容易或可能的。

感谢大家在这个项目中给予的所有支持!!! 现在项目已经进行到了中期,另一位更有经验的程序员将会给我更多的支持,我会向他展示你们所有的评论,并看看他是否能够实现所有建议的更改! - Fernando Carvalho
1
我尝试了您关于使用Wildfly 8.1.0和Hibernate 4.3.5.Final创建RESTful接口的建议。它非常好用,谢谢! - Gerrit Brouwer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接