我使用springBootTest来测试我创建的服务。在每个函数之前,我直接使用存储库创建了一个父属性。
parentEntity = parentEntityRepository.saveAndFlush(ObjectMother.getParentEntityBuilder().string3("s3").build());
在我的测试中我创建了一个子实体
childEntity = childEntityRepository.saveAndFlush(ObjectMother.getChildEntityBuilder().parentEntity(parentEntity).build());
子关系定义如下
@Getter @Setter
@OneToMany(orphanRemoval = true)
@JoinColumn(name="PARENTENTITY_ID", updatable = false)
private Set<ChildEntity> children;
在test
中调用parentEntity = parentEntityService.read(requestContext, parentEntity.getId());
parentEntity.getChildren().forEach(child -> Assert.assertNotNull(child.getText()));
导致以下错误
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.sap.icn.pi.test.data.mcp.ParentEntity.children, could not initialize proxy - no Session
如果我添加@Transactional到我的测试方法,我收到以下
java.lang.NullPointerException // for parentEntity.getChildren()
**编辑:代码片段**
@Test
public void get_children_through_parent() {
parentEntity = parentEntityService.read(requestContext, 1);
parentEntity.getChildren().forEach(child -> Assert.assertNotNull(child));
parentEntity.getChildren().forEach(child -> Assert.assertNull(child.getTooltip()));
}
ParentEntity类
@Entity
@Table(name = "T_PARENTENTITY")
@SequenceGenerator(initialValue = 1, name = "idgen", sequenceName = "SEQ_PARENTENTITY")
@Builder @NoArgsConstructor @AllArgsConstructor
@Localized
public class ParentEntity extends BaseEntity{
... //props
@Getter @Setter
@OneToMany(orphanRemoval = true)
@JoinColumn(name="PARENTENTITY_ID", updatable = false)
private Set<ChildEntity> children;
}
这是一个常见的JPA/Hibernate问题。对象被读取是不同的Hibernate会话或Hibernate会话不再存在,所以延迟加载不能做SQL查询来检索延迟依赖。这种情况的原因各不相同,你没有提供足够的背景。
要解决这个问题,您有各种选项:
- 确保在同一个Hibernate会话中加载对象和惰性依赖。Spring会自动为每个控制器请求创建hibernate会话,因此最好确保您的对象不会在servlet过滤器中检索,也不会在控制器/服务中的惰性依赖项中检索。或者常见的问题是将该对象传递到单独的线程中。
-
将依赖项更改为EAGER:
@Getter @Setter @OneToMany(orphanRemoval = true, fetch = FetchType.EAGER) @JoinColumn(name="PARENTENTITY_ID", updatable = false) private Set<ChildEntity> children;