Hibernate多对多延迟初始化异常

时间:2016-02-05 00:40:24

标签: mysql hibernate spring-boot many-to-many lazy-initialization

我是JEE的新手,最近开始学习Spring和Hibernate。我正在尝试开发RESTful服务来跟踪带有类别的项目。我有多对多关联(一个项目可以有很多类别,一个类别可以有很多项目),三个表:项目,类别和连接表项目_category。

我正在使用MySQL服务器,Spring Boot 1.3.1和Hibernate 4.3

我现在要做的是获取包含类别和类别以及项目列表的项目列表。我用API编写了整个应用程序,最终得到了LazyInitializationException。我尝试了很多方法,但它没有帮助。 (我可以设置获取类型EAGER,但这不是解决方案)。

例如,这是列出所有项目的API:GET /api/item

这是输出:(不是预料到的!):

  

引起:org.hibernate.LazyInitializationException:懒得懒散>初始化角色集合:com.sk.itemlist.domain.Item.categories,无法初始化代理 - 没有会话       at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)~ [hibernate-core-4.3.10.Final.jar:4.3.10.Final]       在org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)〜[hibernate-core-4.3.10.Final.jar:4.3.10.Final]       在org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:155)〜[hibernate-core-4.3.10.Final.jar:4.3.10.Final]       在org.hibernate.collection.internal.PersistentSet.size(PersistentSet.java:160)〜[hibernate-core-4.3.10.Final.jar:4.3.10.Final]       在com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:101)〜[jackson-databind-2.6.5.jar:2.6.5]       at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:24)〜[jackson-databind-2.6.5.jar:2.6.5]       在com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693)〜[jackson-databind-2.6.5.jar:2.6.5]       at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675)~ [jackson-databind-2.6.5.jar:2.6.5]

如果您尝试获取所有类别GET /api/category或ID GET /api/category/1

类别,则会出现同样的错误

所以这是我的问题:

  1. 如何摆脱LazyInitializationException?如何配置hibernate重新打开会话?或者我应该在DAO层初始化集合吗?
  2. 我读到DTO模式,我不完全明白它是什么,我应该深入挖掘这个吗?
  3. 当我尝试将数据插入项目时,我注意到了问题。它只插入项目表,连接表和类别为空。我手动将数据添加到DB中进行测试
  4. 您对整个应用的感觉如何?我可以在这里改进什么或者我应该避免什么(如果有的话)
  5. 最后,我在这里上传了完整的项目:https://gitlab.com/sksh/ItemList.git
    在资源中,您可以使用一些随机数据找到数据库转储。使用有效的数据库凭据更新application.properties。

1 个答案:

答案 0 :(得分:1)

会发生什么:

  • 你要求hibernate获取一些项目
  • Hibernate带来了它们,但没有带来项目类别的信息。
  • 在完成数据库会话工作后尝试访问这些类别时(在CollectionSerializer中),您将获得该异常
  • 你需要让hibernate和项目一起带来类别,这样你就可以在会话结束后使用then(迭代,列表或其他)。

你应该使用像DAO级别那样的东西..

// fetch a Criteria reference and use join fetching
 Criteria c = currentSession().createCriteria(Item.class);
 c.setFetchMode("categories", FetchMode.JOIN);
 c.add(Restrictions.eq("id", id));
 Item result = (Item)c.uniqueResult();
 return result;    

还有其他方法,例如在Item

中声明
@ManyToMany(fetch=FetchType.EAGER) 
private Set<Category> categories = new HashSet<>();

但它可能导致性能问题