2016-08-25 85 views
0

我使用springBootTest来测试我创建的服务。在每个函数之前,我直接使用仓库创建一个parententity。SpringBootTest没有解决父子关系 - 未能延迟初始化

parentEntity = parentEntityRepository.saveAndFlush(ObjectMother.getParentEntityBuilder().string3("s3").build()); 

在我的测试中,我创建一个childentity

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

回答

1

这是常见的JPA/Hibernate问题米对象被读取的是不同的Hibernate会话或hibernate会话不再存在,所以懒加载不能执行SQL查询来检索懒惰依赖。这种情况的原因可能会有所不同,并且您没有提供足够的背景。

为了解决这个问题,你有多种选择:

  1. 确保对象读取和懒惰关系在同一个Hibernate Session加载。 Spring为每个控制器请求自动创建hibernate会话,所以最好确保您的对象不会在servlet过滤器中检索到,并且在控制器/服务中不会检索到惰性依赖关系。或者常见问题是将该对象传递给单独的线程。
  2. 上改变依赖于急于:

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

感谢您的解释。建议2似乎并不合适,因为我不想将我的抓取类型更改为只是为了能够更好地进行测试。 我将如何确保在同一会话中读取对象。我基本上只是使用我的服务层功能。 –

+0

您是否正在通过各种用户请求分享它们? – luboskrnac

+0

分享什么?在测试中,我称之为“e = myservice.read(...)”,之后是“e.getChildren()”,基本上就是这样。我试图添加@Transactional到测试类,这将解决错误,但getChildren将始终返回空值,然后... –