SpringBootTest无法解析父子关系 - 无法进行惰性初始化

时间:2016-08-25 08:26:30

标签: java spring hibernate spring-boot

我使用springBootTest来测试我创建的服务。在每个函数之前,我直接使用存储库创建一个parententity。

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;

在测试中调用

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 Class

@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;
}

1 个答案:

答案 0 :(得分:1)

这是一个常见的JPA / Hibernate问题。对象被读取是不同的Hibernate会话或者hibernate会话不再存在,所以延迟加载不能进行SQL查询来检索延迟依赖。这种情况的原因可能会有所不同,但您没有提供足够的背景信息。

要解决此问题,您有多种选择:

  1. 确保读取对象并在同一Hibernate会话中加载延迟依赖项。 Spring自动为每个控制器请求创建hibernate会话,因此最好确保在servlet过滤器和控制器/服务中的延迟依赖项中不检索对象。或者常见的问题是将该对象传递到单独的线程中。
  2. 将依赖关系更改为EAGER:

    @Getter @Setter
    @OneToMany(orphanRemoval = true, fetch = FetchType.EAGER)
    @JoinColumn(name="PARENTENTITY_ID", updatable = false)
    private Set<ChildEntity> children;