Java JPA lazy fetch不工作并引发LazyInitializationException异常

Java JPA lazy fetch不工作并引发LazyInitializationException异常,java,spring,hibernate,jpa,hibernate-mapping,Java,Spring,Hibernate,Jpa,Hibernate Mapping,我是spring数据JPA的新手,所以我试图从中获得一些东西,以便了解获取模式,但它引发了一个异常,请看一下代码 public class State { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; String name; @OneToMany(mappedBy = "state", cascade = CascadeType.ALL, fetch = FetchType

我是spring数据JPA的新手,所以我试图从中获得一些东西,以便了解获取模式,但它引发了一个异常,请看一下代码

public class State {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Integer id;

  String name;

  @OneToMany(mappedBy = "state", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  Set<Constituency> constituencies ;

  public void fetchLazyCollection() {
    getConstituencies().size();
  }
}

public class Constituency {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Integer id;

  String name;

  @ManyToOne
  @JoinColumn(name = "state_id")
  State state;
}
正如我所假设的,java中的每个单元测试都维护自己与数据库的交互会话,可能我错了,有人能告诉我我在这里做错了什么吗?
任何帮助都将不胜感激。

延迟加载在持久性上下文中有效。事务完成后,无法执行延迟获取。您可以扩展事务范围,以便在事务中获取集合,或者创建将为您返回集合的查询。另一种方法是使用stareRepository方法之一手动获取集合,例如
List states=stateRepository.findByNameAndFetchCollection(“新德里”),其中事务应仍处于活动状态。

您将获得
LazyInitializationException
,因为在您离开
stateRepository.findByName(“新德里”)
之后,Hibernate
会话将关闭,并且您无法在正在运行的Hibernate
会话之外获取其他关联

@Transactional
添加到测试将解决此问题,您不必调用:

states.get(0).fetchLazyCollection();
最好在原始实体查询中获取所需的惰性关联:

select s 
from State s 
left join fetch s.constituencies 
where s.name = :stateName

这是因为您在事务(会话)之外获取惰性集合。所以你有两种方法:

  • 在加载实体的同一会话/事务中获取集合
  • 设置hibernate属性(用于SessionFactory),该属性支持非事务性加载惰性:

    真的


将惰性标志设置为集合映射的true,如下所示

@OneToMany(mappedBy = "objectId", cascade = CascadeType.ALL, orphanRemoval = true , fetch = FetchType.EAGER)

感谢bro,它起作用了,对此有点怀疑,因为您说过findByName是负责打开/关闭会话的方法,所以代表您的声明,我制作了一个StateService对象,在类级别具有@Transactional,它有一个fetchWithCollection方法,我正在其中检索状态,它的集合现在处于单个事务中,我正在从测试中调用此服务方法,但它不起作用,这次也发生了相同的异常,它现在不是单个事务吗?是的,它应该。将新代码添加到要验证的问题中。`@Service@Transactional public class StateService{@Autowired private StateRepository StateRepository;public List getStateWithCollection(字符串名称){List states=StateRepository.findByName(名称);for(状态:states){state.fetchLazyCollection();}return states;}}}这就是我所说的服务。`stateRepository.save(德里);List states=stateService.getStateWithCollection(“新德里”);assertThat(states.get(0.getRecommensions().size(),is(2));`与DB交互的测试部分在这里。很抱歉,无法在注释部分格式化代码。请检查Spring是否知道您的事务注释:tx:annotation-driven。
states.get(0).fetchLazyCollection();
select s 
from State s 
left join fetch s.constituencies 
where s.name = :stateName
@OneToMany(mappedBy = "objectId", cascade = CascadeType.ALL, orphanRemoval = true , fetch = FetchType.EAGER)