2017-07-31 69 views
0

我想在REST控制器中設置一對多的關係,但我得到一個LazyInitializationException。我知道如何解決這個異常(JOIN FETCH,EntityGraph),但不是在DomainClassConverter的背景下。LazyInitializationException當使用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:

@Repository 
public interface CompanyRepository extends JpaRepository<Company, Long> { 
} 

@Repository 
public interface ContractRepository extends JpaRepository<Company, Long> { 
} 

A 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

我結束了不使用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); 
    } 

} 
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); 
} 

相關信息:12

+0

的'findOne'不會獲取延遲的集合。 – Sydney

相關問題