2015-10-11 100 views
1

我與Hibernate通過JPA工作(後端測試是H2,但同樣的問題發生在其他引擎)和他們加入可選列和過濾時都遇到了問題。加入可選列JPA和休眠

,我有以下數據模型:

@Entity 
public class Ticket { 
    @Id 
    private long id; 

    @ManyToOne(optional = true) 
    @Nullable 
    private Assignee assignee; 
} 

@Entity 
public class Assignee { 
    @Id 
    private long id; 

    private String name; 
} 

而且三個實體:

  • Assignee{id = 1, name = kitty}
  • Ticket{id = 1, assignee = null}
  • Ticket{id = 2, assignee = 1}

現在,我正在使用jpql查詢門票:

  • select t from Ticket t會按預期產生兩張門票。
  • select t from Ticket t where t.assignee is null僅按預期產生票1。
  • select t from Ticket t where t.assignee.name = :namename=kitty僅按預期產生票2。

然而,一個OR子句中的兩個過濾器連接在一起不表現爲預期:select t from Ticket t where (t.assignee is null or t.assignee.name = :name)name=kitty僅產生票2,同時該查詢應匹配票1以及(因爲受讓人可以爲空)。當檢查休眠調試日誌,會生成以下SQL查詢:

SELECT 
    ticket0_.id   AS id1_1_, 
    ticket0_.assignee_id AS assignee2_1_ 
FROM Ticket ticket0_ CROSS JOIN Assignee assignee1_ 
WHERE ticket0_.assignee_id = assignee1_.id AND (ticket0_.assignee_id IS NULL OR assignee1_.name = ?) 

條件ticket0_.assignee_id = assignee1_.id顯然是永遠不會滿足的票1,因爲它沒有受讓人,因爲Hibernate翻譯錯誤此查詢。

我有什麼辦法解決這個問題嗎?

+0

這? http://stackoverflow.com/questions/11654023/how-do-i-query-hibernate-for-object-where-property-may-be-null-or-specific-value – slckin

+0

@slckin不,這是一個不同的API 。 – yawkat

回答

0

在您SELECT語句,表明該表達t.assignee.name。雖然您尚未在SELECT語句中明確使用JOIN操作,但從Ticket實體遍歷到Assignee實體以獲取name屬性將需要2個實體之間的NATURAL JOIN。因此,您將在輸出SQL中看到一個ticket0_.assignee_id = assignee1_.id

你可以重寫你的查詢:

SELECT t from Ticket t WHERE (t.assignee IS NULL) OR (t.assignee IS NOT NULL AND t.assignee.name = :name) 

,或者嘗試使用外連接來代替:

SELECT t FROM Ticket t LEFT JOIN Assignee a WHERE a.name = :name