2013-02-19 1 views
7

Ich versuche, eine grundlegende Abfrage mit JPQL in Spring Data zu optimieren, um mehrere Abfragen an die Datenbank zu vermeiden und alle Informationen in einer Abfrage mithilfe von Join Fetch und I abzurufen halten diese Ausnahme erhalten:JPQL Join Fetch funktioniert nicht in ManyToOne Zuordnung in Spring Daten

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) 

Das ist mein Dao:

/** 
* 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); 
} 

Und das sind meine Einheiten:

@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(); 
    } 
} 

Alle Einsichten, Hilfe würde sehr geschätzt werden.

Die reine SQL für das, was ich will das etwas aussehen würde, erreichen:

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 
+0

, wie (und warum) können Sie eine Tasche verbinden holen, während nur die Anzahl der Rückkehr () –

+0

Hey Guido, nur wundernd, warum hier eine Tasche, jeder CoApplicant sollte nur einen Staat und nur ein Land damit verbunden haben. Die folgende reine SQL-Abfrage für das, was ich will Werke erreichen, völlig in Ordnung: SELECT ca.Id , vorName , nachName , recognitionName , AddressLine1 , Stadt , E-Mail , MAINPHONE , coun.name , sta.name VON coApplicants AS ca LEFT JOIN Länder AS coun \t auf ca.country_Id = coun.id links sta Staaten JOIN \t auf ca.state_Id = sta.id – vanvasquez

+2

ich das gleiche Problem haben, ist das Problem mit dem " Seite "und" FETCH ", wenn Sie es mit List ersetzen, wird es perfekt funktionieren. hast du die lösung gefunden, wenn ja bitte teile es mit uns :) –

Antwort

10

Mit einer durchgeblättert Abfrage mit JOIN FETCH ist ein Thema für Hibernate.

Um die Situation zu lösen, müssen Sie countQuery platzieren - fast das gleiche wie das Original, aber unabhängige INNER JOINs (eventuell FETCHes) werden entfernt.

Quelle der Lösung hier gefunden werden: Spring-Data FETCH JOIN with Paging is not working

für Sie also die Lösung sein:

@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); 
+0

Danke viel joro, was du vorgeschlagen hast funktioniert einwandfrei. – vanvasquez

+0

Endlich habe ich das gefunden. Danke vielmals! –

+0

aber wir sollten ein Komma zwischen zwei Parametern von @Query hinzufügen –

Verwandte Themen