У меня ниже сопоставления как 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
содержит null
для companyFunds
, т.е. загрузка LAZY работает нормально до тех порточка. Но в тот момент, когда выполняется return companyResource;
, что-то идет внутри Spring, и оператор Select
для CompanyFund
запускается. Я отладил шаги, и ниже приведен код (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
с контроллера, ничего неожиданного не произойдет. Ленивая загрузка работает нормально.