程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Hibernate中的"Repeated column in mapping for entity"異常,hibernaterepeated

Hibernate中的"Repeated column in mapping for entity"異常,hibernaterepeated

編輯:JAVA綜合教程

Hibernate中的"Repeated column in mapping for entity"異常,hibernaterepeated


轉:http://lijiejava.iteye.com/blog/786535

一對多雙向關聯(類Item與類Bid):

Item類:

public class Item {   
    private int id;   
    private String name;   
    private Set bids = new HashSet();  
    •••  
}

 

Bid類:

public class Bid {   
    private int id;   
    private double amount;   
    private Item item;  
    •••  
}

Item.hbm.xml:(t_item表)

<hibernate-mapping>  
    •••  
        <set name="bids" table="t_bid" cascade="save-update">  
            <key column="item_id" not-null="true"/>  
            <one-to-many class="value.Bid"/>  
        </set>   
    •••   
</hibernate-mapping>

Bid.hbm.xml: (t_bid表):

<hibernate-mapping>  
    •••  
<many-to-one name="item" class="value.Item" column="item_id" not-null="true" />   
    •••  
</hibernate-mapping>

測試代碼:

•••  
Item item = new Item();  
item.setName("item");  
          
Bid b1 = new Bid();  
b1.setAmount(12.09);   
b1.setItem(item);  
          
Bid b2 = new Bid();  
b2.setAmount(11.98);   
b2.setItem(item);  
          
Set bids = new HashSet();  
bids.add(b1);  
bids.add(b2);  
          
item.setBids(bids);   
          
session.beginTransaction();    
session.save(item);   
session.getTransaction().commit();

這是以前的一個"一對多雙向關聯",今天運行時拋出了如下異常:

Exception in thread "main" java.lang.ExceptionInInitializerError  
•••  
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: value.Bid column: item_id (should be mapped with insert="false" update="false")

仔細檢查了映射文件,發現在Item.hbm.xml配置文件的<key>元素中多了一個not-null="true"限制,將其去掉後就可以正常運行。

(1) 加入not-null="true"意味著什麼?


由<key>元素定義的列映射item_id是t_bid表的外鍵列。加入not-null="true"之後,意味著如果要增加t_bid表中的記錄,那麼外鍵列item_id一定不能為null,Item端為了確保item_id字段不為null(Item端不知道Bid端的情況,所以它不可能依賴Bid端來確保item_id不為空),會在t_bid的插入語句中為該字段賦值。
事實上,不論是單向一對多還是雙向一對多,只要在<key>元素中設置了not-null="true",那麼在t_bid表的insert語句中都會增加column屬性所指定的列(此處即item_id),以此確保item_id列不為空。以單向一對多關聯為例:如果未設定not-null="true",那麼輸出的語句為:Hibernate: insert into t_bid (amount) values (?);而如果設定了not-null="true",那麼輸出的語句就是:Hibernate: insert into t_bid (amount, item_id) values (?, ?) 。

(2) 拋出異常的原因?


異常的原因可以從異常信息中看出,即字段重復。通過(1)中的分析,可以很清楚地明白其中的原因。查看Bid.hbm.xml映射文件:
<many-to-one name="item" class="value.Item" column="item_id" not-null="true" />
可以看出,這是一個多對一關聯,not-null="true"表明一個Bid肯定有其對應的Item實體。column屬性指定t_bid表中item_id列是t_item表主鍵的一個外鍵。對於Bid而言,不論是否指定了not-null="true",它的insert語句都會為item_id字段賦值,即使為null。這就是異常產生的原因,這樣的設置會使Hibernate發出類似 insert into t_bid (item_id,item_id) values (•••)的語句,所以會提示重復字段異常。

(3) 解決:


1. 把<key>元素中的not-null="true"去掉,事實上在雙向關聯中根本不需要由Item端來確保外鍵列item_id不為null。
2. 可以按照提示,在Bid.hbm.xml映射文件中加入insert="false" update="false"。
加入這兩個限制,意味著對t_bid表的insert與update操作中不包含這個字段,這樣可避免重復。
3. 在Item.hbm.xml中的<set>元素內加入inverse="true",將關聯關系全部交給Bid端。http://lijiejava.iteye.com/blog/776587
4. 最無聊的方法:將<key>元素中的column值改成item_id_1等,不與item_id重復,這樣會導致數據表字段的冗余,不應該使用。
在實際應用中,不應該在<key>中加入not-null="true"限制。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved