2009-11-25 78 views
3

我嘗試使用下面的代碼插入或更新數據庫記錄:休眠saveOrUpdate失敗,當我執行它的空表

Category category = new Category(); 
category.setName('catName'); 
category.setId(1L); 
categoryDao.saveOrUpdate(category); 

當有一個id = 1已經在數據庫中一切正常的類別。但是,如果沒有 記錄使用id = 1我得到了以下異常:

org.hibernate.StaleStateException: 
Batch update returned unexpected row count from update [0]; actual row count: 0; 
expected: 1: 

這裏是我的Category類setter方法,getter和構造中省略爲清楚:

@Entity 
public class Category {  
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    private String name; 

    @ManyToOne 
    private Category parent; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "parent") 
    private List<Category> categories = new ArrayList<Category>(); 
} 

在我看到這個控制檯休眠查詢:

update 
    Category 
set 
    name=?, 
    parent_id=? 
where 
    id=? 

所以看起來像冬眠tryis更新記錄,而不是插入新的。我在這裏做錯了什麼?

回答

5

這是設計。

Hibernate只根據id決定它是否應該執行更新或插入。如果它會考慮數據庫中已存在的內容,那麼它將不得不執行額外的查詢,但它不會執行此操作。

Ids通常由Hibernate管理,除非將其映射爲generator="assigned"(不知道如何使用註釋看起來如此)。所以你不應該爲它分配一個值。

在這種情況下,Id甚至由數據庫給出。所以如果您的應用程序會同時生成Ids,則會導致重複的Ids。 (並且大多數數據庫不允許將值插入到自動列中,所以在技術上不可能存儲您的ID)。

如果要生成自己的ID,請使用generator="assigned",並使用merge存儲它。這將做你所期望的:它搜索數據庫中的記錄,當它存在時它會更新它,否則它會插入它。

+0

我只是想,如果我手動設置編號hibernate將能夠識別,如果記錄已經在數據庫中,並將執行更新,如果沒有,它將執行保存。所以在我的情況下,你建議手動檢查對象的存在,然後選擇保存或更新? – Vladimir 2009-11-25 11:24:03

+0

你可以這樣做。但是 - 你不應該寫入由數據庫管理的Id或休眠。所以這種情況不應該發生。您必須爲誰應該生成該ID做出選擇。 – 2009-11-25 16:38:25

0

如果表的rowcount爲0,則嘗試單獨使用save方法else使用saveorupdate方法。

+0

...當有另一個記錄? – 2009-11-25 11:21:12