【发布时间】:2021-03-13 14:42:16
【问题描述】:
当我试图懒惰地读取子实体列表时,我(间歇性地)收到此错误。
failed to lazily initialize a collection of role: G.h, could not initialize proxy - no Session
关于这个错误,我浏览了关于 SO 的帖子列表。我所能找到的只是做 EAGER fetch 或使用 hibernate.enable_lazy_load_no_trans 属性。我也不想这样做,因为它们是反模式。
而且我在从数据库读取数据的类级别上确实有@Tranastional(readOnly=true),所以我希望休眠会话在事务完成之前一直打开。
此外,此错误仅偶尔弹出一次。大多数时候根本没有问题。另一件事是,我可以确认实体是延迟加载的(除了我明确指定 EAGER 的地方),因为我可以看到在读取实体时记录了 sql 语句。
这是我的代码在坚果壳中的样子。
@Service
@Transactional(readOnly = true)
public class AService {
public void someMethod(Long id) {
Optional<A> a = ARepository.findById(id); // This is a standard JPA repository interface where I have defined a method findById
final Optional<G> g = getG(a.get());
if (g.isPresent()) {
for (final H h : g.get().getH()) { // Exception is thrown exactly at line ..getH()
}
}
}
private Optional<G> getG(final A a) {
return a.getB()
.getD()
.getF()
.flatMap(F::getG);
}
}
@Entity
public class A implements Serializable {
@ManyToOne
private AGroup aGroup;
@Transient
public Optional<B> getB() {
return getC().map(C::getB);
}
public Optional<C> getC() {
if (aGroup != null) {
return Optional.ofNullable(aGroup.getC());
}
return empty();
}
}
@Entity
public class AGroup implements Serializable {
@ManyToOne
private C c;
@OneToMany(fetch = EAGER, cascade = ALL, mappedBy = "aGroup")
private final Set<A> as = new HashSet<>();
}
@Entity
public class C implements Serializable {
@OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "c")
private List<AGroup> aGroups = new ArrayList<>();
@ManyToOne
private B b;
}
@Entity
public class B implements Serializable {
@OneToMany(fetch = LAZY, mappedBy = "b")
private Set<C> cs = new HashSet<>();
@ManyToOne(fetch = LAZY)
private D d;
}
@Entity
public class D implements Serializable {
@OneToMany(fetch = LAZY, mappedBy = "d")
private final List<B> bs = new ArrayList<>();
public Optional<F> getF() {
// based on some other fields return Optional.of(F)
}
}
@Entity
public class F implements Serializable {
@ManyToOne
private G g;
public Optional<G> getG() {
return Optional.ofNullable(g);
}
}
@Entity
public class G implements Serializable {
@OneToMany(mappedBy = "g")
private List<F> fs = new ArrayList<>();
@OneToMany(cascade = ALL, mappedBy = "g")
private List<H> hs = new ArrayList<>();
}
@Entity
public class H {
@ManyToOne
private G g;
}
任何人都知道是什么导致了这个问题(更重要的是,为什么会间歇性发生这种情况)
我正在使用 spring-data-jpa。这是一个spring-boot项目。请求来自 web 层(Rest Controller)
【问题讨论】:
标签: spring-boot hibernate spring-data-jpa spring-data lazy-loading