【发布时间】:2021-08-30 07:38:02
【问题描述】:
我遇到了org.hibernate.LazyInitializationException,原因在this question 中有很好的解释。我认为,我的代码与链接中引用的问题存在相同的问题。代码如下:
合同类:
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Contract implements Serializable {
@Id
@Column(name = "uuid")
private UUID uuid;
@Column(name = "settlement_date")
private LocalDate settlementDate;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "contract")
private Set<ContractFile> files;
}
合同文件类:
@Entity
@NoArgsConstructor
@Getter
@Setter
public class ContractFile implements Serializable {
@Id
@Column(name = "uuid")
private UUID uuid;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "contract_uuid")
private Contract contract;
public ContractFile(final Contract contract) {
uuid = UUID.randomUUID();
this.contract = contract;
}
}
这就是我遇到麻烦的地方。这是一个 DTO,我需要通过从 ContractFile 对象中检索合同来从合同中获取结算日期。
@Getter
public class DTO {
private String reference;
public DTO(final ContractFile contractFile) {
final Contract contract = contractFile.getContract();
this.reference = "reference_" + receivable.getSettlementDate();
}
}
据我了解,我在文件 this.reference = "reference_" + receivable.getSettlementDate(); 上得到了 org.hibernate.LazyInitializationException,因为由于缺少 Spring Context,合同对象一开始就没有正确初始化。如果这个假设是正确的,我该如何做到这一点,以便当我在这个 DTO 中执行 contractFile.getContract() 时,我打开了正确的代理?我已经看到了很多关于为什么我的代码不能工作以及它应该在哪个环境中工作的解释,但是没有示例代码,如果没有一个 repository 对象直接从数据库中检索合同,我想不出如何做到这一点。
编辑 1 这是在另一个类中使用 DTO 的方式,负责端点通信:
public String report(Set<DTO> dto) {
return executePost(properties.getUri(), new DTOList(dto), String.class);
}
编辑 2
对我来说,诀窍是将 @Transactional 设置为从数据库获取 ContractFiles 的方法。
//this transactional opens the context for all
//methods called from reportAll.
@Transactional
public void reportAll() {
final Set<ContractFile> contracts = contractFileService
.findAll();
contracts.forEach(this::report);
}
public void report(final ContractFile contractFile) {
final String response = infraService.report(contractFile);
log.info("Reported successfully");
}
【问题讨论】:
-
DTO 在哪里使用?
-
在另一个类中,负责端点通信,如问题中所编辑。
-
LazyInitializationException如果您尝试在无法检索到属性的位置访问Lazy属性(即没有可用的会话可通过询问 DB/Persistence 来检索该属性),则会发生。您的问题应该通过使用“OpenSessionInViewFilter”来解决。这应该如何完成取决于您的项目设置。