2009-07-09 59 views
5

我有一個用戶對象與字符串類型具有一對多的關係。我相信他們是簡單的映射。類型表保存關聯的user_id和變量類型名稱,主鍵「id」基本上是一個計數器。休眠保存奇怪的行爲

<class name="Users" table="users"> 
    <id column="id" name="id" /> 
    ... 
    <set name="types" table="types" cascade="save-update"> 
     <key column="id" /> 
     <one-to-many class="Types" /> 
    </set> 
</class> 

<class name="Types" table="types"> 
    <id column="id" name="id" /> 
    <property column="user_id" name="user_id" type="integer" /> 
    <property column="type" name="type" type="string" /> 
</class> 

這是我用於添加到數據庫中的Java:當我檢查SQL

61468 [http-8080-3] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1062, SQLState: 23000 
61468 [http-8080-3] ERROR org.hibernate.util.JDBCExceptionReporter - Duplicate entry '6' for key 'PRIMARY' 
61468 [http-8080-3] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session 
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update 

,它:

User u = new User(); 
u.setId(user_id); 
... 
Collection<Types> t = new HashSet<Types>(); 
t.add(new Type(auto_incremented_id, user_id, type_name)); 
u.setTypes(t); 

getHibernateTemplate().saveOrUpdate(u); 

當我運行它,它給這個錯誤顯示:

Hibernate: insert into users (name, id) values (?, ?) 
Hibernate: insert into types (user_id, type, id) values (?, ?, ?) 
Hibernate: update types set id=? where id=? 
  • 爲什麼Hibernate嘗試更新類型的ID?

錯誤說:關鍵'PRIMARY'重複條目'6',但真的沒有?我確保每次都增加id。用戶和類型正確添加到數據庫中。

我記錄了進去的信息,添加的類型有一個id爲7,用戶id是6.可能是Hibernate的user_id是6,試圖更新類型並設置id = 6,其中id = 7?因此重複的主鍵錯誤?

但是它爲什麼會這麼奇怪?有沒有辦法阻止它更新?

  • 我應該手動設置ID嗎?如果不是,那麼我應該如何添加這些類型?當我添加只有一個類型字符串和沒有ID的類型對象時,它會給出其他錯誤。

謝謝你們。我們已經仔細研究了幾天...

回答

2

您最大的問題是<key>映射中的錯誤列 - 它應該是「user_id」,而不是「id」。也就是說,你的整個映射對我來說似乎有點奇怪。

首先,如果你想要的ID自動生成的,你真的應該讓Hibernate通過指定合適的發電機照顧的是:

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

閱讀Hibernate Documentation發電機上的各種可用的選項。

其次,如果你需要的是一組字符串類型的,考慮重新映射到它們的元素的集合,而不是一個一對多的關係:

 
<set name="types" table="types"> 
    <key column="user_id"/> 
    <element column="type" type="string"/> 
</set> 

這樣,你就不需要顯式的「類型」類或它的映射。即使您確實希望在「類型」上具有其他屬性,您仍然可以將其映射爲組件而不是實體。

最後,如果「類型」必須是一個實體,由於沒有描述的一些要求,「用戶」和「類型」之間的關係是雙向的,需要被映射爲這樣的:

 
<set name="types" table="types" inverse="true"> 
    <key column="user_id"/> 
    <one-to-many class="Types"/> 
</set> 

... 
in Types mapping: 
<many-to-one name="user" column="user_id" not-null="true"/> 

在後一種情況下,「類型」必須具有「用戶」類型的「用戶」屬性。 Here是一個詳細的例子。

+0

套牢元素集合!謝謝! – April 2009-07-13 14:33:14

0

爲我工作的解決方案是單獨保存的兩個部分(不添加類型到用戶):

getHibernateTemplate().save(user); 
getHibernateTemplate().save(new Type(user.id, type_name)); 

並與/>僅在類型ID的<發生器類=「天然的」。

不良做法?

已將其映射爲元素的集合,但它有時錯誤地將user_id添加到類型id列,這有時會導致重複錯誤;因爲類型id是唯一的主鍵列。奇怪的!我記得有一些其他的列錯誤,但忘了它,因爲我立即恢復爲一對多。無法掌握Hibernate的怪運作...

我有時會嘗試雙向解決方案......非常感謝所有幫助:)

+1

恐怕你完全錯過了這一點。你應該讓Hibernate讓你的生活更輕鬆,而不是每一步都要與它作鬥爭 - 並且正確的映射對於實現這一點將會有很大的幫助。上面描述的情景是非常基本的;有很多可用的例子(我已經在我的答案中發佈了鏈接)。你確實需要閱讀文檔,使其工作,並理解_how_它的工作原理;否則在路上會變得更加困難。 – ChssPly76 2009-07-10 16:58:46