2014-11-03 104 views
0

我是Hibernate的新手,我試圖動態加入更多的表。我用三個表格構建了一個例子:員工,地址,國家。我想檢索某個國家的所有員工。在這裏我的配置文件:休眠:動態連接多個表

<class entity-name="Employee"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="firstName" column="first_name" type="string"/> 
     <property name="lastName" column="last_name" type="string"/> 
     <property name="salary" column="salary" type="int"/> 

     <many-to-one name="address" column="address" unique="true" 
        class="Address" not-null="true"/> 
    </class> 

    <class entity-name="Address"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="street" column="street_name" type="string"/> 
     <property name="city" column="city_name" type="string"/> 
     <property name="state" column="state_name" type="string"/> 
     <property name="zipcode" column="zipcode" type="string"/> 

     <many-to-one name="country" column="country" unique="true" 
        class="Country" not-null="true"/> 
    </class> 

    <class entity-name="Country"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="name" column="name" type="string"/> 
     <property name="code" column="code" type="string"/> 
    </class> 

如果我做

List employees = session.createCriteria("Employee") 
      .createCriteria("address") 
      .createCriteria("country") 
      .add(Restrictions.eq("code","IT")) 
      .list(); 

我得到正確的結果回來,但我的目標不是要手動指定開始表和篩選器表之間的整個路徑:我想是休眠爲我工作。我想編寫這樣的事:

List employees = session.createCriteria("Employee") 
      .createCriteria("country") 
      .add(Restrictions.eq("code","IT")) 
      .list(); 

,但我得到的錯誤信息

org.hibernate.QueryException: could not resolve property: country of: Employee 

回答

1

Hibernate是隻是一個包裝或抽象層遁形SQL表達式。

在您的工作示例的Hibernate構建一個SQL SELECT語句創建一個雙JOIN和返回所需的輸出。您正在向Hibernate提供如何過濾關聯表的「知識」。和你自己寫SQL語句一樣。

但是在你的第二個例子中,你希望Hibernate從第一個表猜測第二級關聯。如果表僱員有一個列/外鍵國家,它沒有找到它,休眠只是查找。所以錯誤是:無法解決屬性:國家:員工

你不能指望從Hibernate做這種魔術,因爲它會產生或排序錯誤的查詢。

只是爲了說明你的例子。

如果你的員工將有類型地址的兩個領域:

<class entity-name="Employee"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="firstName" column="first_name" type="string"/> 
     <property name="lastName" column="last_name" type="string"/> 
     <property name="salary" column="salary" type="int"/> 

     <many-to-one name="bussiness_address" column="bussiness_address" unique="true" 
        class="Address" not-null="true"/> 
     <many-to-one name="home_address" column="home_address" unique="true" 
        class="Address" not-null="true"/> 
    </class> 

雙方將有一個國家聯繫......我應該在此查詢的情況下冬眠嗎?

List employees = session.createCriteria("Employee") 
      .createCriteria("country") 
      .add(Restrictions.eq("code","IT")) 
      .list(); 

業務地址或兩個過濾器的國家嗎? 或者想象一下,您在每個表格中都會顯示id字段。

所以包東西:Hibernate無法使用魔法,只有在這裏躲遠原始的SQL。

1

如果我翻譯查詢到Java語言,你正在試圖做的是越來越coutry的價值直接從員工的。在Java中,你會得到一個編譯錯誤。這種東西在Java,Hibernate或普通SQL中都不會自動工作。員工和國家之間沒有直接聯繫,但員工 - >地址 - >國家有一系列鏈接。

要以Java方式解決此問題,可以直接從員工維護對國家的次要引用。然後調用employee.getAddress()。getCountry()和employee.getCountry()將是平等的。

爲了在hibernate中實現這一點,您需要向Employee添加新的字段國家,並將其映射爲與實體Country不可修改的多對多關係,使用實體Address映射關係。這隻會將2個hibernate聯接減少到1個,它不能反覆應用於超過2個聯接。

如果這個解決方案對您來說可以,我可以爲您提供示例語法。

+0

好的,我理解你的比較。關鍵是Hibernate有一個查詢(構建器)引擎,但它不能像我所想的那樣動態地在圖中的兩個實體之間找到路徑。 – Zardo 2014-11-11 09:55:30

+0

你是對的。 Hibernate需要在查詢中加入一個從員工到國家/地區實體的路徑 – OndrejM 2015-01-07 11:19:19