【问题标题】:JPA returning a nested object after creation - 500 Internal Server ErrorJPA 在创建后返回嵌套对象 - 500 内部服务器错误
【发布时间】:2019-09-14 22:27:30
【问题描述】:

我有我的主要对象:

@Data
@Entity
@EqualsAndHashCode(callSuper = false)
@Table(name = MAIN_OBJ)
public class MainObj {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "MAIN_OBJ_ID", unique = true, nullable = false)
    private Integer manObjId;

    @ManyToOne
    @JoinColumn(name = "SUB_OBJ_ID", referencedColumnName = "SUB_OBJ_ID", nullable = false)
    @NotNull
    private SubObj subObj;

}

它是子对象:

@Data
@Entity
@EqualsAndHashCode(callSuper = false)
@Table(name = SUB_OBJ)
public class SubObj {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "SUB_OBJ_ID", unique = true, nullable = false)
    private Integer subObjId;

    @Column(name = "NAME", nullable = false)
    @NotNull
    private String name;

}

当我进行创作时:

@Override
@Transactional
public MainObj create(MainObj mainObj) {
    MainObj createdMainObj = mainObjRepository.save(mainObj);
    return createdMainObj;
}

它可以正确保存,但是当我将它返回给用户(通过控制器返回)时,我得到了 500 的回报。调试后我可以看到 subObj 中的所有字段都是空的。

但它确实创建了 mainObj 并将其放入数据库中,它只是无法将其序列化并返回。

如果我追踪它,我会看到:

找不到类的序列化程序 org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer

不太确定我需要添加什么,以便我可以将完全创建的对象及其对 subObj 的外键引用返回给用户。

我尝试了 Hibernate.initialize() 就像很多帖子说的那样,但没有运气。

如果不清楚,它会给我其中之一:

完整的堆栈跟踪(删除了一些细节):

org.springframework.http.converter.HttpMessageNotWritableException: 无法写入 JSON:找不到类的序列化程序 org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer 并且没有 发现创建 BeanSerializer 的属性(为了避免异常, 禁用 SerializationFeature.FAIL_ON_EMPTY_BEANS);嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException:没有序列化程序 找到上课 org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer 并且没有 发现创建 BeanSerializer 的属性(为了避免异常, 禁用 SerializationFeature.FAIL_ON_EMPTY_BEANS)(通过引用 链: com.path.to.MainObj["subObj"]-com.path.to.SubObj_$$_jvsta14_f["handler"])

【问题讨论】:

  • 您能否将@ManyToOne 更改为@ManyToOne(fetch = FetchType.EAGER) 之类的东西,请阅读它以了解性能影响。
  • @AdilKhalil fetch = EAGER @ManyToOne的默认值
  • 这是我不明白的主要内容,为什么当它是一个 EAGER 负载时,LazyInitializer 完全参与其中?

标签: java spring hibernate jpa


【解决方案1】:

你能试试这个吗? 将此注解添加到 SubObj 类中

@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="SUB_OBJ_ID")

【讨论】:

  • 你会把它放在什么文件上?
  • 已经在我的评论中提到了@canpan14:你在 SubObj Class(model) 上面添加了这个注解
  • 哦,我瞎了!谢谢!
  • 415 不支持的媒体类型。 path.to.SubObj 的无效对象 ID 定义:找不到名称为“SUB_OBJ_ID”的属性
  • 我尝试用 subObjId 来匹配变量名,结果又回到原来的 500 错误。
【解决方案2】:

最好的做法是不要直接在控制器中返回实体(因为它可能会导致堆栈溢出异常)。实体应转换为 DTO(数据传输对象)并返回 DTO。

如果你仍然想使用实体,你应该对所有引用使用eager而不是lazy(包括引用对象内的引用对象);

【讨论】:

  • ManyToOne 默认是 Eager。我们正在将其转换为 DTO。但这无济于事,因为子对象保持在那种奇怪的状态,如果你在调试器中打开它,它会说一切都是空的,并且上面有一个“处理程序”。如果您打开处理程序,您可以在其下找到对象的完整定义。
猜你喜欢
  • 1970-01-01
  • 2017-08-26
  • 1970-01-01
  • 2021-11-12
  • 2013-07-24
  • 1970-01-01
  • 1970-01-01
  • 2013-06-11
  • 2014-03-25
相关资源
最近更新 更多