【问题标题】:LazyInitializationException when using DomainClassConverter使用 DomainClassConverter 时出现 LazyInitializationException
【发布时间】:2017-07-31 20:11:02
【问题描述】:

我想在 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);
    }

}

【问题讨论】:

    标签: spring spring-mvc spring-data-jpa


    【解决方案1】:

    尝试像这样更改您的控制器方法:

    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

    【讨论】:

    • findOne 不会获取惰性集合。
    【解决方案2】:

    我最终没有使用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);
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 2015-07-31
      • 1970-01-01
      • 1970-01-01
      • 2021-04-28
      相关资源
      最近更新 更多