【发布时间】:2013-02-03 15:56:30
【问题描述】:
我正在尝试在 Spring Data 中使用 JPQL 优化基本查询,以避免对数据库进行多次查询并使用 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
【问题讨论】:
-
如何(以及为什么)加入 fetch a bag,同时只返回 count()?
-
嘿,guido,只是想知道为什么这里有一个包,每个 CoApplicant 应该只有一个州和一个与之关联的国家。以下纯 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
-
我也有同样的问题,问题出在“Page”和“FETCH”,如果你用 List 替换它,它会完美运行。您找到解决方案了吗,如果是,请与我们分享:)
标签: hibernate jpa spring-data-jpa