I came across a org.hibernate.LazyInitializationException
which the cause is very well explained in this question. My code has, I think, the same problem as in the question referenced in the link. Here's the code:
Contract class:
@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;
}
ContractFile class:
@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;
}
}
And here's where I'm having trouble. This is a DTO, in which I need to get a settlementDate from a Contract by retrieving the Contract from a ContractFile object.
@Getter
public class DTO {
private String reference;
public DTO(final ContractFile contractFile) {
final Contract contract = contractFile.getContract();
this.reference = "reference_" + receivable.getSettlementDate();
}
}
It is my understandment that I'm getting org.hibernate.LazyInitializationException
on the file this.reference = "reference_" + receivable.getSettlementDate();
because the Contract objects wasn't properly initialized to begin with, due to the lack of a Spring Context
. If this assumption is correct, how do I make it so that when I do contractFile.getContract()
inside this DTO I have proper proxy opened? I've seen many explanation as to why my code won't work and the environment in which it should, but no sample code and I cannot think of how accomplish this without having a repository
object retrieving the contract directly from database.
EDIT 1 This is how DTO is used, in another class, responsible for endpoint communication:
public String report(Set<DTO> dto) {
return executePost(properties.getUri(), new DTOList(dto), String.class);
}
EDIT 2
What did the trick for me was to set @Transactional
to the method that gets the ContractFiles from database.
//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");
}