java - SpringBootTest 无法解析父子关系 - 未能延迟初始化

标签 java spring hibernate spring-boot

我正在使用 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;

这在测试中调用

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 session 不同或 Hibernate session 不再存在,因此延迟加载无法执行 SQL 查询来检索延迟依赖项。造成这种情况的原因可能有所不同,并且您没有提供足够的背景信息。

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

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

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

关于java - SpringBootTest 无法解析父子关系 - 未能延迟初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39140235/

相关文章:

java - 设置边距时,相对布局中的按钮会被压扁

java - Spring bean 模板

java - 关于@Access,Hibernate 不符合 JPA 标准吗?

java - EAP 7.3 JPA+Hibernate REST 双向 ManyToOne 关系序列化(非 SPRING)

java - 如何在 Spring 中显示下载文件名中的非法字符?

java - 没有可用的托管连接

java - 尝试使用 Java 中的 equals() 比较两个字符串

java - Intellij IDEA - 在路径字符串文字中查找,如何避免解释为正则表达式?

java - 如何在removeKeyListener之后使用addKeyListener?

java - mvn 测试失败,但从 IntelliJ IDEA 运行测试通过