JPQL Join Fetch не работает в ассоциации ManyToOne в весенних данных
Я пытаюсь оптимизировать базовый запрос с помощью JPQL в данных Spring, чтобы избежать нескольких запросов к базе данных и получить всю информацию в одном запросе с помощью JOIN Fetch, и я продолжаю получать это исключение:
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=Business.Countries,tableAlias=country1_,origin=BUSINESS.COAPPLICANTS coapplican0_,columns={coapplican0_.Country_Id ,className=com.medifast.entity.core.Country}}] [select count(ca) from com.medifast.entity.core.CoApplicant ca LEFT JOIN FETCH ca.country LEFT JOIN FETCH ca.state where ca.client.id = :clientId]; nested exception is java.lang.IllegalArgumentException: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=Business.Countries,tableAlias=country1_,origin=BUSINESS.COAPPLICANTS coapplican0_,columns={coapplican0_.Country_Id ,className=com.medifast.entity.core.Country}}] [select count(ca) from com.medifast.entity.core.CoApplicant ca LEFT JOIN FETCH ca.country LEFT JOIN FETCH ca.state where ca.client.id = :clientId]
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:301)
Это мой Дао:
/**
* Interface to handle persistence operations for CoApplicants.
*
*/
@Repository
public interface ICoApplicantDao extends JpaRepository<CoApplicant, Long>
{
@Query("select ca from CoApplicant ca JOIN FETCH ca.country c where ca.client.id = :clientId")
Page<CoApplicant> findCoApplicantsByClient(@Param("clientId") Long clientId, Pageable pageable);
}
и это мои сущности:
@Entity
@Table(name = "BUSINESS.COAPPLICANTS")
@SQLDelete(sql = "UPDATE BUSINESS.COAPPLICANTS SET DELETED = 1 WHERE id = ?")
@Where(clause = "DELETED <> 1")
@Data
@EqualsAndHashCode(callSuper = true)
public class CoApplicant extends AbstractAuditableEntity
{
/**
* Serial.
*/
private static final long serialVersionUID = -297231024073091062L;
/**
* First name.
*/
@Column(name = "FirstName")
private String firstName;
/**
* Last name.
*/
@Column(name = "LastName")
private String lastName;
/**
* Recognition Name.
*/
private String recognitionName;
/**
* For the address line 1 field.
*/
private String addressLine1;
/**
* For the address line 2 field.
*/
private String addressLine2;
/**
* City.
*/
private String city;
/**
* State.
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "State_Id")
private State state;
/**
* Zip Code.
*/
private String zipCode;
/**
* Country.
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "Country_Id")
private Country country;
/**
* Email address.
*/
@Column(unique = true)
private String email;
/**
* Main Phone number.
*/
private String mainPhone;
/**
* Constructor.
*/
public CoApplicant()
{
super();
}
}
/**
* Country entity.
*/
@Entity
@Table(name = "Business.Countries")
@SQLDelete(sql = "Update Business.Countries set deleted = 1 where id=?")
@Where(clause = "deleted <> 1")
@Data
@EqualsAndHashCode(callSuper = true)
public class Country extends AbstractAuditableEntity
{
/**
* Serial.
*/
private static final long serialVersionUID = -267110442898674427L;
/**
* Name of the country.
*/
private String name;
/**
* The orders for the client.
*/
@OneToMany(mappedBy = "country", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Collection<State> states;
/**
* Const.
*/
public Country()
{
super();
}
}
/**
* State entity.
*/
@Entity
@Table(name = "Business.States")
@SQLDelete(sql = "Update Business.States set deleted = 1 where id=?")
@Where(clause = "deleted <> 1")
@Data
@EqualsAndHashCode(callSuper = true)
public class State extends AbstractAuditableEntity
{
/**
* Serial.
*/
private static final long serialVersionUID = 8643487990581006632L;
/**
* Name of the state.
*/
private String name;
/**
* Code of the state.
*/
private String code;
/**
* Country to which this State belongs.
*/
@ManyToOne
@JoinColumn(name = "Country_Id")
private Country country;
/**
* Constr.
*/
public State()
{
super();
}
}
любые идеи, помощь будет высоко оценена.
чистый SQL для того, что я хочу выполнить, будет выглядеть примерно так это:
SELECT ca.Id
,firstName
,lastName
,recognitionName
,addressLine1
,city
,email
,mainPhone
,coun.name
,sta.name
FROM coApplicants AS ca
LEFT JOIN countries AS coun
on ca.country_Id=coun.id
LEFT JOIN states AS sta
on ca.state_Id=sta.id
1 ответов
используя pageable запрос с JOIN FETCH
является проблемой для Hibernate.
, чтобы решить ситуацию, вы должны поместить countQuery
- почти то же самое, что и исходные, но несвязанные внутренние соединения (в конечном итоге выборки) удаляются.
источник решения можно найти здесь:Spring-Data FETCH JOIN с подкачкой не работает
такое решение для вас будет:
@Query(
value="select ca from CoApplicant ca JOIN FETCH ca.country c where ca.client.id = :clientId",
countQuery="select count(ca) from CoApplicant ca where ca.client.id = :clientId")
Page<CoApplicant> findCoApplicantsByClient(@Param("clientId") Long clientId, Pageable pageable);