【发布时间】:2021-12-17 18:09:49
【问题描述】:
我在使用 spring 时遇到了延迟初始化异常。我知道这是一个常见错误,并且我已经解决了几个堆栈问题,但没有一个答案真的对我有用。这是我的场景:我有两个这样相关的类:
public class Foo implements Serializable {
@Id
@EqualsAndHashCode.Include
@Column(name = "uuid")
private UUID uuid;
@Column(name = “attribute”)
private String attribute;
@OneToMany(fetch = FetchType.LAZY, mappedBy = “foo”)
private Set<Bar> bar;
}
public class Bar implements Serializable {
@Id
@Column(name = "uuid")
private UUID uuid;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = “foo_uuid")
private Foo foo;
}
我有一个列出所有 Bar 对象的休息端点。在那个特定的端点中,我需要返回 attribute,它是一个 Foo 属性。由于在应用程序业务逻辑中不需要这样做,因此似乎也没有必要将 attribute 添加到 Bar 中。所以我有一个BarWrapper类,它是Bar的自定义格式,由端点返回:
@Getter
@Setter
@NoArgsConstructor
public class BarWrapper {
…
private String attribute;
public BarWrapper(final Bar bar) {
//The next line throws lazy initialization exception.
this.attribute = bar.getFoo().getAttribute()
}
我在所有课程上都尝试过@Transactional,但没有奏效。我尝试添加cascade = CascadeType.ALL,这确实有效,但不是一个好习惯。我也尝试为此创建一个自定义函数,但也没有帮助:
@Transactional
private String extractAttribute(final Bar bar){
final Foo foo = bar.getFoo();
return foo.getAttribute();
}
如何克服这个延迟初始化异常?
编辑:
这就是我调用 BarWrapper 构造函数的方式:
@AllArgsConstructor
@Service
@Slf4j
public class BarApplicationServices {
private final FooService fooService;
private final BarService barService;
public BarWrapper createBar(final CreateBarRequestBody requestBody) {
final Foo foo = fooService.findFooToBeSettled(requestBody.getFooUuid());
final Bar createdBar = barService
.createBar(new Bar(foo));
return new BarWrapper(createdBar);
}
}
【问题讨论】:
-
BarWrapper的构造函数怎么调用?向我们展示那里的代码,它应该在 Service 方法中,您可以在该方法中从数据库中加载Bar实体,以确保调用bar.getFoo()将在同一个事务中。 -
你为什么在 Bar 类中懒惰地初始化 Foo 对象?
-
@memoricab 这是一个相当大的对象,我实际上并不经常使用。
-
@pleft 按要求添加了代码。
-
但是如果你懒惰地获取那个对象,你就看不到它的内容,对吧?那么当您尝试访问尚未获取的内容时,它会引发异常,这不是很正常吗?
标签: java spring spring-boot jpa java-11