2012-08-06 49 views
8

我有兩個表 - 一個包含地址,另一個包含照片。他們之間唯一的共同領域是PersonID。這些映射到兩個POJO類地址和照片。我能夠通過創建標準並在字段中添加限制來獲取這些表中的詳細信息。我們應該如何在兩個表上編寫連接。是否有可能將結果作爲兩個對象 - 地址和照片。如何使用JPA和休眠加入兩個不相關的實體

我想做一個左連接,這樣我可以得到人的記錄,而不照片爲好。 我讀過,這是可能的只能使用hql,但這可以使用標準來完成?

回答

10

你可以很容易地編寫HQL查詢,它將使用Theta Join返回結果作爲兩個對象(如Adrian指出的那樣) 。下面是一個示例:

String queryText = "select address, photo from Address address, Photo photo where address.personID=photo.personId"; 
List<Object[]> rows = session.createQuery(queryText).list(); 

for (Object[] row: rows) { 
    System.out.println(" ------- "); 
    System.out.println("Address object: " + row[0]); 
    System.out.println("Photo object: " + row[1]); 
} 

正如您所看到的,查詢返回表示每個獲取行的Object []數組的列表。這個數組的第一個元素將包含一個obejct和第二個元素 - 另一個。

編輯:

在左側的情況下,加入我認爲你需要使用原生SQL查詢(不HQL查詢)。在這裏你如何做到這一點:

String queryText = "select address.*, photo.* from ADDRESS address 
        left join PHOTO photo on (address.person_id=photo.person_id)"; 

List<Object[]> rows = sess.createSQLQuery(queryText) 
          .addEntity("address", Address.class) 
          .addEntity("photo", Photo.class) 
          .list(); 

這應該適合你的情況。

+0

感謝您的示例,但我們可以做一個左連接...我曾嘗試使用「地址左連接照片」,但發生以下錯誤...「外連接或全連接必須跟隨路徑表達式」 – juan 2012-08-06 07:58:07

+0

好。我編輯了我的答案併爲左連接添加了示例。我認爲這應該適合你。 – dimas 2012-08-06 08:16:48

+0

@dimas我們是否可以在左連接中使用hql – dom 2017-01-25 15:12:31

0

你所尋找的是

  1. HQL
  2. 加入對你還沒有建模爲關係領域
  3. 左連接

(在時間問題首先被問及這個答案) Hibernate支持Theta加入,它允許你做1 & 2.但是,只有內連接可用於theta連接樣式。

個人而言,我會建議你適當的關係進行建模,所以你只需要1 & 3這是良好的支持HQL。

(另一個答案實際上提供了新的休眠功能,可提供這種功能的更新,你可以簡單地指)

+0

不知道爲什麼它被拒絕投票。答案實際上是正確的(即使是基於此的被接受的答案),我也舉了一些例子,僅僅是因爲在給出所提供的關鍵信息的情況下找到它是微不足道的。並且稍後給出左連接要求 – 2015-11-05 22:50:43

+0

@Ismael我會重新修改它,但我不認爲我所說的是不完整的:沒有正確的方式使用HQL來實現OP所要求的。 Theta加入是他能夠得到的最接近的,但是因爲它不是在做他所做的事情,所以我不打算舉例說明。 – 2016-07-14 03:19:23

0

最好是有一個包含你想加入讓他們一起這些類的類。

但是,如果你只是偶爾有一些目的連接這些表,你可以使用標準和手動加載每個表中的數據,並把它們放在一起。 (是的,如果Address和Photo有兩個獨立的類和表,你可以分別獲得這些表的數據)

+0

馬丁請你詳細說明一下。我如何爲這種情況創建一個類? – underdog 2015-10-30 16:50:46

+0

使用您在連接中擁有的屬性創建一個班級。這個類應該綁定到一個數據庫表,其中包含實體之間關係的名稱。 (這裏我們稱它們爲'address_photo_rel'表)。因此,當hibernate爲你的類創建表時,這個連接表也被創建。 _如果你不這樣做,並且由於你的實體(這裏是'address'和'photo')之間有關係,hibernate最終會創建該表,但是你無法控制這個表,因爲你沒有類爲它._ – 2015-11-02 20:09:04

3

最後經過12年的休眠團隊implemented such a feature

Hibernate docs

FROM子句也可以包含明確的關係聯接使用join關鍵字。這些連接可以是內部或左外部樣式連接。您可以使用WITHON關鍵字。這些

的註記的重要區別是,在生成的SQL的WITH條件 /ON子句是由在生成 SQL ON子句的一部分,如在本節相對於其他查詢其中 HQL/JPQL條件成爲生成的 SQL中的WHERE子句的一部分。

List<Object[]> personsAndPhones = session.createQuery(
    "select pr.name, ph.number " + 
    "from Person pr " + 
    "left join pr.phones ph with ph.type = :phoneType ") 
.setParameter("phoneType", PhoneType.LAND_LINE) 
.list(); 

我現在渴望嘗試新的功能。

3

正如我在this article解釋,你有兩個選擇:

  1. 因爲Hibernate的5.1,你可以使用ad-hoc joins不相關的實體。

    Tuple postViewCount = entityManager.createQuery(
        "select p as post, count(pv) as page_views " + 
        "from Post p " + 
        "left join PageView pv on p.slug = pv.slug " + 
        "where p.title = :title " + 
        "group by p", Tuple.class) 
    .setParameter("title", "High-Performance Java Persistence") 
    .getSingleResult(); 
    
  2. 在Hibernate 5.1之前,您只能使用theta樣式的連接。然而,一個theta樣式的連接相當於一個equijoin,因此您只能模擬INNER JOIN而不是OUTER JOIN。

    List<Tuple> postViewCount = entityManager.createQuery(
        "select p as post, count(pv) as page_views " + 
        "from Post p, PageView pv " + 
        "where p.title = :title and " + 
        "  (p.slug = pv.slug) " + 
        "group by p", Tuple.class) 
    .setParameter("title", "Presentations") 
    .getResultList(); 
    

有關詳細信息,請this article

+0

以前的版本是否有其他選擇。我正在使用hibernate-entitymanager-5.0.9,它給了我「加入的路徑!」錯誤 – 2017-05-29 13:14:01

+0

您可以使用theta風格的連接。 – 2017-05-29 13:39:37