2010-07-07 80 views
2

我正在開發一個程序來存儲和管理測試結果。測試具有日期,持續時間和結果等屬性。然而,一些測試測量壓力,其他溫度......我希望你明白。所以,不是每個測試都有相同的屬性。休眠:混合動態(基於映射)和靜態(基於Bean)映射

我的第一個想法是將測試結果從測試表中提取到各個結果表中,從而創建1:1關係。爲了保持測試結果的可擴展性,我希望將結果存儲在地圖中而不是Bean中。

但是,似乎Hibernate不喜歡我的方法。有沒有人有這種映射的經驗?有更好的選擇嗎?


實施例EDIT和進一步解釋

-------- 
| Test | 
|id  | 
+--------+ 
|date | 
|duration| 1  1 ---------- 
|...  | --------- | Medium | 
--------   |testID | 
        +----------+ 
        |medium | 
        |pressure | 
         ---------- 

介質將是一個測試可以有一個屬性。由於可以添加其他屬性,我不想對中等類進行硬編碼,而是將其映射爲Map,並存儲這三個屬性。我的想法是,測試將有一個Map<String, Map<String, Object>>來表示與之相關的所有屬性。

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
     "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping package="com.hoerbiger.versuchsdb.domain"> 
<class name="Test" lazy="false"> 

    <id name="id"> 
    <generator class="native"/> 
    </id> 

    <property name="datum"/> 

    <many-to-one name="material" class="Material"/> 

    <set name="testgeraete" table="Test_Testgeraet" lazy="false"> 
    <key column="testID"/> 
    <many-to-many column="geraetID" class="Testgeraet"/> 
    </set> 

    <!-- Here it's getting important --> 

    <one-to-one name="medium" entity-name="Medium" constrained="false" lazy="false" 
       access="com.hoerbiger.versuchsdb.hibernate.TestAccessor"/> 

</class> 
</hibernate-mapping> 

com.hoerbiger.versuchsdb.hibernate.TestAccessor是訪問,我想使用的關係

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
     "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping package="com.hoerbiger.versuchsdb.domain"> 
<class entity-name="Medium" lazy="false"> 

    <id name="id" type="long"> 
    <generator class="foreign"> 
    <param name="property">id</param> 
    </generator> 
    </id> 

    <one-to-one name="id" class="Test" constrained="true"/> 

    <property name="medium" type="string"/> 

    <property name="pressure" type="int"/> 

</class> 
</hibernate-mapping> 

要嘗試什麼可行的地圖PropertyAccessor接口,我用這個主要方法。注意最後幾行

@SuppressWarnings("unchecked") 
public static void main(String[] args) { 
    Session s = Helper.getSessionfactory().getCurrentSession(); 
    s.beginTransaction(); 
    //Change to dynamic session 
    s = s.getSession(EntityMode.MAP); 

    Map<String, Object> test = (Map<String, Object>) s.createQuery("from Test").iterate().next(); 
    //for me, prints "25" 
    System.out.println(test.get("id")); 

    Map<String, Object> medium = new HashMap<String, Object>(); 
    medium.put("id", test); 
    medium.put("medium", "Luft"); 
    medium.put("pressure", 40); 

    s.save("Medium", medium); 
    s.getTransaction().commit(); 
    System.out.println("---"); 
    s = Helper.getSessionfactory().getCurrentSession(); 
    s.beginTransaction(); 

    Test t = (Test) s.createQuery("from Test").iterate().next(); 
    //for me, prints "null, 2010-07-07 00:00:00.0" (Test.toString()) 
    System.out.println(t); 
    //"25" 
    System.out.println(t.getId()); 
    //"{medium={id=null, 2010-07-07 00:00:00.0, ...}}" 
    System.out.println(t.getProperties()); 
    //"true" 
    System.out.println(t.getProperties().get("medium").get("id") == t); 

    //This is really weird - hibernate loads the map with a Test stored, but when 
    //saving, it expects a Long. With this line, the Commit succeeds 
    t.getProperties().get("medium").put("id", t.getId()); 
    s.getTransaction().commit(); 
} 

這些最後一行是怎麼回事?這是一個在休眠或錯誤配置的錯誤?

+0

爲什麼你想要一個映射如果關係是1:1?我認爲展示一些Java代碼(一個基本的例子)將有助於理解你想實現什麼。另外,您是否使用XML映射或註釋?何種版本的Hibernate(在JPA 2.O之前)? – 2010-07-08 03:16:51

+0

嗨!感謝您的幫助,試圖完善我的問題,我學到了很多東西。我正在使用3.5.3,並將編輯我的問題到現在出錯的地方 – 2010-07-08 07:54:39

回答

1

多一點電文讀出後,我就什麼我的錯誤是:目前,我的媒體映射是這樣的:

<hibernate-mapping package="com.hoerbiger.versuchsdb.domain"> 
<class entity-name="Medium" lazy="false"> 

    <id name="id" type="long"> 
    <generator class="foreign"> 
    <param name="property">id</param> 
    </generator> 
    </id> 

    <one-to-one name="id" class="Test" constrained="true"/> 

    <property name="medium" type="string"/> 

    <property name="pressure" type="int"/> 

</class> 
</hibernate-mapping> 

但它應該是這樣的:

<hibernate-mapping package="com.hoerbiger.versuchsdb.domain"> 
<class entity-name="Medium" lazy="false"> 

    <id name="id" type="long"> 
    <generator class="foreign"> 
    <param name="property">test</param> 
    </generator> 
    </id> 

    <one-to-one name="test" class="Test" constrained="true"/> 

    <property name="medium" type="string"/> 

    <property name="pressure" type="int"/> 

</class> 
</hibernate-mapping> 

問題在發生器中使用「id」和一對一約束

Hibernate使用兩個屬性來表示主鍵一對一約束,在我的情況下:

  • id是PK & FK,即test.getId(),長
  • 試驗是參照異物它的自我

由於地圖不是類型安全的,你可以覆蓋由測試首先存儲的Long。這兩個值都只讀入相同的地圖條目。通過更改兩次id來測試,引用有自己的條目,不會覆蓋id值