指定是否使用Spring Data延迟加载
我在实体中有一个懒惰的fetch类型集合。 我正在使用Spring Data(JpaRepository)来访问实体。
@Entity public class Parent{ @Id private Long id; @OneToMany(mappedBy = "parentId", fetch = FetchType.LAZY) private Set children; }
我想在服务类和当前实现中有两个函数如下:
-
获取父级时,“children”应为null
public Parent getParent(Long parentId){ return repo.findOne(parentId); }
-
取父母时应填写“孩子”:
public Parent getParentWithChildren(Long parentId){ Parent p = repo.findOne(parentId); Hibernate.initialize(p.children); return p; }
从RestController返回“Parent”实体时,抛出以下exception:
@RequestMapping("/parent/{parentId}") public Parent getParent(@PathVariable("parentId") Long id) { Parent p= parentService.getParent(id);//ok till here return p;//error thrown when converting to JSON }
org.springframework.http.converter.HttpMessageNotWritableException:无法写内容:懒得初始化角色集合:com.entity.Parent.children,无法初始化代理 – 无会话(通过引用链:com.entity.Parent [ “孩子们”]); 嵌套exception是com.fasterxml.jackson.databind.JsonMappingException:懒得初始化一个角色集合:com.entity.Parent.children,无法初始化代理 – 没有Session(通过引用链:com.entity.Parent [“children “])
如果您希望根据用例允许同一域模型的不同JSON表示,那么您可以查看以下内容,这样您就可以在不需要DTO的情况下执行此操作:
https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring
或者,另请参阅下面的“Spring Data REST中的预测”部分
https://spring.io/blog/2014/05/21/what-s-new-in-spring-data-dijkstra#projections-in-spring-data-rest
RestController应返回ParentDTO
而不是Parent
实体。 可以在Transactional服务方法中填充ParentDTO
。
抛出exception是因为JSON序列化程序要求已初始化所有属性。 因此,所有需要返回Parent的REST控制器必须首先初始化属性:
@RequestMapping("/parent/{parentId}") public Parent getParent(@PathVariable("parentId") Long id) { return parentService.getParentWithChildren(id); }
getParentWithChildren
服务方法在事务内部运行,并且在提交事务时关闭关联的Hibernate会话。 这意味着您必须在Hibernate Session仍处于打开状态时(在Service方法内)初始化所有属性。
您还可以使用Spring Data实体图形支持:
@Entity @NamedEntityGraphs(@NamedEntityGraph(name = "Parent.children", attributeNodes = @NamedAttributeNode("children"))) public class Parent{ @Id private Long id; @OneToMany(mappedBy = "parentId", fetch = FetchType.LAZY) private Set children; }
并且getParentWithChildren
方法变为:
@Repository public interface ParentRepository extends CrudRepository { @EntityGraph(value = "Parent.children", type = EntityGraphType.LOAD) Parent getParentWithChildren(Long parentId); }
所以,你甚至不需要实现:
- 的getParent
- getParentWithChildren
这些方法可以由Spring Data提供。
首先,您没有向我们展示Child
Java类:我希望该属性名为parentId
而不是parent
:
public class Child { @ManyToOne private Parent parentId; }
解决方案1:您的代码实际上是正确的,只需要使用第二层DTO (简单的POJO类)将域层传输到客户端/浏览器。 如果你不这样做,在解决你的懒惰exception后,你会遇到从父到子的循环依赖问题,而JSON编组(jackson)会尝试编码一个Child
,然后是它的Parent
,然后再编译它的子代,然后又是他们的Parent
等等。 DTO的一个例子是:
public class ParentDto { private Long id; private String prop1; public ParentDto(Parent parent) { this.id = parent.id; this.prop1 = parent.prop1; //...other properties } //here come all getters for the properties defined above. }
解决方案2:将@JsonIgnore用于公共属性Parent.getChildren()
,以便Jackson在编组Parent
实例时不会尝试Parent.getChildren()
进行编码。
- Hibernate-懒得初始化一个角色集合:beans.Language.patients,无法初始化代理 – 没有Session
- 无法执行存储过程JPA
- 例外:无法解析配置:hibernate.cfg.xml
- 如何使用jpa和hibernate将本机查询映射到POJO类
- 在抽象的JPA DAO中抽象命名查询
- 从@ OneToMany-association中删除子项:CascadeType.ALL + orphanRemoval = true not working
- Hibernate – 自定义插入数据库
- 在Spring / JPA / Mysql / Tomcat应用程序中分析Connection Closed Exception
- Hibernate:映射未找到exception