2012-08-14 12 views
2

下面是我的數據庫的快速圖。JPQL:多重連接。如何做我的namedquery?

http://img17.imageshack.us/img17/2474/mpd.png

在這個方案中,我創建JPA實體(有一個紅色的方形所有表)。

我想創建一個JPQL查詢來獲取所有具有引用的引擎,引用由參數給定的引用類型定義的引用。

我想: SELECT DISTINCT a FROM Aircraft a JOIN FETCH a.references r WHERE EXISTS (SELECT ref FROM Reference ref WHERE ref = r AND ref.referenceType.id = :id)

但我有一個錯誤的原因Eclipse的犯規像JOIN FETCH a.references *r*別名和JUnit測試的要求不工作。

這裏我沒有實體的getter/setter方法:

飛機

@Entity 
@Table(name = "T_R_AIRCRAFT_AIR", uniqueConstraints = @UniqueConstraint(columnNames = "AIR_NAME")) 
public class Aircraft implements java.io.Serializable { 

    @Id 
    @Column(name = "AIR_ID", unique = true, nullable = false) 
    @TableGenerator(name="aircraftSeqStore", 
     table="T_S_APP_SEQ_STORE_AST", 
     pkColumnName="AST_SEQ_NAME", 
     valueColumnName = "AST_SEQ_VALUE", 
     pkColumnValue = "T_R_AIRCRAFT_AIR.AIR_ID", 
     allocationSize=1) 
    @GeneratedValue(strategy=GenerationType.TABLE, 
     generator="aircraftSeqStore")  
    private Integer id; 

    @Column(name = "AIR_NAME", unique = true, nullable = false, length = 50) 
    private String name; 

    @ManyToMany(fetch = FetchType.LAZY) 
    @JoinTable(name = "T_J_REF_AIR_RFA", 
       joinColumns = { @JoinColumn(name = "RFA_AIR_ID", nullable = false, updatable = false) }, 
       inverseJoinColumns = { @JoinColumn(name = "RFA_REF_ID", nullable = false, updatable = false) }) 
    private Set<Reference> references = new HashSet<Reference>(0); 

    @ManyToMany(fetch = FetchType.LAZY) 
    @JoinTable(name = "T_J_MAN_AIR_MNA", 
       joinColumns = { @JoinColumn(name = "MNA_AIR_ID", nullable = false, updatable = false) }, 
       inverseJoinColumns = { @JoinColumn(name = "MNA_MAN_ID", nullable = false, updatable = false) }) 
    private Set<Manual> manuals = new HashSet<Manual>(0); 

    @OneToMany(fetch = FetchType.LAZY, 
       mappedBy = "aircraft", 
       cascade = { CascadeType.REMOVE }) 
    private Set<UserConfig> userConfigs = new HashSet<UserConfig>(0); 
} 

** **參考

@Entity 
@Table(name = "T_E_REFERENCE_REF", 
     uniqueConstraints = @UniqueConstraint(columnNames = "REF_IDENTIFIER")) 
public class Reference implements java.io.Serializable { 

    @Id 
    @Column(name = "REF_ID", unique = true, nullable = false) 
    @TableGenerator(name="referenceSeqStore", 
     table="T_S_APP_SEQ_STORE_AST", 
     pkColumnName="AST_SEQ_NAME", 
     valueColumnName = "AST_SEQ_VALUE", 
     pkColumnValue = "T_E_REFERENCE_REF.REF_ID", 
     allocationSize=1) 
    @GeneratedValue(strategy=GenerationType.TABLE, generator="referenceSeqStore")     
    private Integer id; 

    @Column(name = "REF_IDENTIFIER", unique = true, nullable = false, length = 50) 
    private String identifier; 

    @Column(name = "REF_LINK") 
    private String link; 

    @Column(name = "REF_OBSERVATIONS", length = 4000) 
    private String observations; 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "REF_RFT_ID", nullable = false) 
    private ReferenceType referenceType; 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "REF_MAN_ID")  
    private Manual manual; 

    @OneToMany(fetch = FetchType.LAZY, 
       mappedBy = "reference", 
       cascade = { CascadeType.REMOVE }) 
    private Set<Translation> translations = new HashSet<Translation>(0); 

    @ManyToMany(fetch = FetchType.LAZY) 
    @JoinTable(name = "T_J_REF_AIR_RFA", 
       joinColumns = { @JoinColumn(name = "RFA_REF_ID", nullable = false, updatable = false) }, 
       inverseJoinColumns = { @JoinColumn(name = "RFA_AIR_ID", nullable = false, updatable = false) }) 
    private Set<Aircraft> aircrafts = new HashSet<Aircraft>(0); 
} 

** **引用類型

@Entity 
@Table(name = "T_R_REFERENCE_TYPE_RFT", 
     uniqueConstraints = @UniqueConstraint(columnNames = "RFT_TYPE")) 
public class ReferenceType implements java.io.Serializable { 

    @Id 
    @Column(name = "RFT_ID", unique = true, nullable = false) 
    @TableGenerator(name="referenceTypeSeqStore", 
     table="T_S_APP_SEQ_STORE_AST", 
     pkColumnName="AST_SEQ_NAME", 
     valueColumnName = "AST_SEQ_VALUE", 
     pkColumnValue = "T_R_REFERENCE_TYPE_RFT.RFT_ID", 
     allocationSize=1) 
    @GeneratedValue(strategy=GenerationType.TABLE, generator="referenceTypeSeqStore")     
    private Integer id; 

    @Column(name = "RFT_TYPE", unique = true, nullable = false, length = 50)  
    private String type; 

    @OneToMany(fetch = FetchType.LAZY, 
       mappedBy = "referenceType", 
       cascade = { CascadeType.REMOVE })  
    private Set<Reference> references = new HashSet<Reference>(0); 

    @OneToMany(fetch = FetchType.LAZY, 
       mappedBy = "referenceType", 
       cascade = { CascadeType.REMOVE })  
    private Set<UserConfig> userConfigs = new HashSet<UserConfig>(0); 
} 

PS:我忘了說在飛機和參考之間增加了一張桌子。這是手冊表。但我不認爲有影響。

PS2:JPA實現由Hibernate完成。

任何想法如何使多重連接? 謝謝!

+0

如何加入一個已經從一個連接的實體?即如何將A與B一起加入C?加入A與B,加入C與C但是對於其他人加入我並不成功似乎很容易。 – MychaL 2012-08-14 19:35:13

回答

4

您可以執行查詢更加容易如下:

SELECT DISTINCT a FROM Aircraft a JOIN FETCH a.references r 
LEFT JOIN FETCH a.manuals 
WHERE r.referenceType.id = :id 

我增加join fetch a.manuals否則我LazyInitializationException。增加了LEFT以防止手冊缺乏影響輸出。

+0

最後,我有一個用我的JUnit測試的pb。太多的延遲加載,這麼多的集合被加載,我有一個outofmemory。我對JPQL有困難。所以我不知道,如果我的JPQL工作與否。在聯合抓取後放置別名似乎不被JPA Validator接受。暫時你的答案不允許我瞭解它是如何工作的。這個JPQL可能是正確的:'SELECT DISTINCT FROM FROM Aircraft a JOIN FETCH a.references JOIN FETCH a.references.referenceType WHERE a.references.referenceType.id =:id'?感謝您的耐心等待。 – MychaL 2012-08-15 16:27:59

+0

不,此查詢不起作用,因爲此路徑「a.references.referenceType」無效。想想你自己:你引用'引用'集合的referenceType'屬性,後者顯然沒有。 – 2012-08-15 16:41:49

+0

我知道使用連接抓取完成「加載」爲延遲加載配置的集合嗎? 那麼有可能創建一個嵌套查詢?在SQL中,我們可能首先通過查詢來選擇ReferenceType Id的所有引用,然後通過一些關節來獲取飛機(通過連接表)。 – MychaL 2012-08-15 17:29:41