RestController:返回Resource <>使FetchType.LAZY表现为FetchType.EAGER

问题描述 投票:1回答:1

我在下面具有与Company具有1:N关系的CompanyFunds的映射

@Entity
public class Company{

    @Id
    private Integer companyId;

    private String name;

    @OneToMany(mappedBy = "company")
    private List<CompanyFund> companyFunds;

}

@Entity
public class CompanyFunds{

    @Id
    private Integer fundId;

    private String name;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "company_id")
  private Company company;

}

我正在为持久层使用Spring-data-Jpa,下面是控制器和服务方法:

//controller
@GetMapping(value = "/{companyId}")
public Resource<Company> find(@PathVariable Integer companyId) {

  Resource<Company> companyResource = companyService.find(companyId);
  return companyResource;
}

//service
public Resource<CompanyTypeOther> find(Integer companyId) {
  Company company =  companyRepository.findById(companyId);

  return restResourceAssembler.toResource(company);
}


@Component
public class RestResourceAssembler implements ResourceAssembler<T, Resource<T>> {

    private EntityLinks entityLinks;

    public RestResourceAssembler(EntityLinks entityLinks) {
        this.entityLinks = entityLinks;
    }

    @Override
    public  Resource<T>  toResource(T entity) {
        Resource<T> resource = new Resource<>(entity);
        resource.add(entityLinks.linkToSingleResource(entity.getClass(), entity.getId()).withSelfRel());

        return resource;
    }
}

[现在很奇怪,直到return companyResource;(在控制器中)未执行之前,companyResource包含nullcompanyFunds,即LAZY加载在此之前工作正常。但是,在执行return companyResource;的那一刻,Spring内部就会发生某些事情,并且会触发SelectCompanyFund语句。我调试了步骤,下面是负责此操作的代码(try块):

public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {

  ......

  public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
    ........other code
    try {
      this.returnValueHandlers.handleReturnValue(
          returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
    }
    catch (Exception ex) {
      if (logger.isTraceEnabled()) {
        logger.trace(formatErrorForReturnValue(returnValue), ex);
      }
      throw ex;
    }
  }

  .....

}

实体中没有声明toString(),也没有调用getCompanyFund()。无法理解Spring在上面的returnValue中所做的事情,因此调用了一些吸气剂(或其他东西)。

我注意到的另一件事是,仅当返回Resource<Company>时才会出现此问题。如果我从控制器返回Company,则不会发生任何意外情况。延迟加载工作正常。

spring spring-boot spring-mvc spring-restcontroller
1个回答
0
投票

由于我想延迟加载该实体,所以一些修复/黑客为我解决了这个问题(截至目前)。

@JsonIgnore
@OneToMany(mappedBy = "company")
private List<CompanyFund> companyFunds;

@JsonIgnore阻止对LAZY加载的实体进行序列化。所以我想杰克逊是罪魁祸首。

这不是我的观点,只是做这件事的一种技巧。仍在等待Spring小组的人答复。

© www.soinside.com 2019 - 2024. All rights reserved.