12

データベースへの複数のクエリを回避し、JOIN Fetchを使用して1つのクエリですべての情報を取得するために、Spring DataでJPQLを使用して基本的なクエリを最適化しようとしていますが、次の例外が発生し続けます。

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
4

1 に答える 1

17

でページング可能なクエリを使用することJOIN FETCHは、Hibernateの問題です。

この状況を解決するには、配置する必要があります。countQuery元の結合とほぼ同じですが、無関係の内部結合(最終的にはFETCH)が削除されます。

ソリューションのソースはここにあります:Spring-ページングを使用したデータFETCHJOINが機能していません

したがって、解決策は次のようになります。

@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);
于 2014-08-20T10:53:11.250 に答える