2017-07-31 55 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

相关问题