我想在REST控制器中设置一对多关系,但我得到一个LazyInitializationException
。我知道如何解决该异常(JOIN FETCH,EntityGraph),但不知道DomainClassConverter
的上下文。
DomainClassConverter允许您在Spring中使用域类型 MVC控制器方法直接签名,这样就不必了 通过存储库手动查找实例
@Entity
public class Company implements Serializable {
@OneToMany(mappedBy = "company")
@JsonIgnore
private Set<Contract> contracts = new HashSet<>();
public Company addContract(Contract contract) {
this.agreements.add(contract);
contract.setCompany(this);
return this;
}
}
@Entity
public class Contract implements Serializable {
@ManyToOne
private Company company;
}
存储库:
@Repository
public interface CompanyRepository extends JpaRepository<Company, Long> {
}
@Repository
public interface ContractRepository extends JpaRepository<Company, Long> {
}
POST /api/companies/1/contracts
请求映射createContract
方法。参数已正确映射,因此我有一个Contract
和一个Company
实例。当我尝试将合同添加到公司时,我得到LazyInitializationException
。我尝试在方法中添加@Transactional
并在company.getContracts()上调用.size()来初始化集合,但它会抛出相同的异常。
@RestController
@RequestMapping("/api/companies/{companyId}")
public class CompanyContractResource {
@PostMapping("/contracts")
@Timed
public ResponseEntity<Contract> createContract(@Valid @RequestBody Contract contract, @PathVariable("companyId") Company company) throws URISyntaxException {
company.addContract(contract);
Contract result = contractRepository.save(contract);
return ResponseEntity.created(new URI("/api/contracts/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
.body(result);
}
}
答案 0 :(得分:0)
尝试更改您的控制器方法:
public ResponseEntity<Contract> createContract(@Valid @RequestBody Contract contract, @PathVariable("companyId") Long companyId) throws URISyntaxException {
// fetching a company explicitly
Company company = companyRepository.findOne(companyId);
company.addContract(contract);
Contract result = contractRepository.save(contract);
return ResponseEntity.created(new URI("/api/contracts/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
.body(result);
}
答案 1 :(得分:0)
我最终没有使用DomainClassConverter
。我更改了存储库以获取延迟集合,然后添加Contract
。
@Repository
public interface CompanyRepository extends JpaRepository<Company, Long> {
@Query(value = "SELECT c FROM Company c LEFT JOIN FETCH c.contracts WHERE c.id = ?1")
Company findByIdWithContracts(Long id);
}
在控制器中:
@RestController
@RequestMapping("/api/companies/{companyId}")
public class CompanyContractResource {
@PostMapping("/contracts")
@Timed
public ResponseEntity<Contract> createContract(@Valid @RequestBody Contract contract, @PathVariable("companyId") Long companyId) throws URISyntaxException {
Company company = companyRepository.findByIdWithContracts(companyId);
company.addContract(contract);
Contract result = contractRepository.save(contract);
return ResponseEntity.created(new URI("/api/contracts/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
.body(result);
}
}