2012-10-09 166 views
0

我有實體Foo,它映射到具有一些唯一約束的sql表。因此保存Foo可能會失敗。我使用FooDao保存Foo違反約束失敗

@Repository 
public class FooDao 
{ 
    @Autowired 
    private SessionFactory sessionFactory; 

    @Transactional 
    @Override 
    public void add(Foo item) { 
    sessionFactory.save(item); 
    } 
} 

當我打電話方法FooDao#add(Foo)它可能會失敗,原因有二:因爲任何違反唯一約束(在這種情況下,我知道如何處理這個問題),或者因爲一些其他問題(在這個我可能應該傳播異常)。我如何區分這兩種情況?

我可以將方法find(Foo item)添加到FooDao並檢查是否類似項目,我試圖添加的是數據庫。但是這需要從數據庫中進行額外的選擇,我對此有點擔心。

回答

1

這就是實際的SQLState。

做這樣的事情

Catch(HibernateException he){ 
    SQLException sqe = he.getSQLEception(); 
    String sqlState = sqe.getSQLState(); 
    if(sqlState.equals("23000"){ 
     // Handle your exception 
    } 
} 

Java文檔: 的SQLState - 標識異常的XOPEN或SQL:2003代碼異常

一個鏈接,我發現了ISO的SQLStates,

link to reference

但是尋找確切的參考和價值..

+0

在我的情況下,HibernateException將被Spring包裝,但我猜SQLState是我正在尋找的。 –

0

一個明顯的(但也許是令人討厭的)解決方案是,您捕獲javax.persistence.PersistenceException並解析錯誤消息「violant」或「constraint」。

從我的角度來看,你應該做選擇/尋找最前沿。請記住,您正在使用ORM! Hibernate包含緩存,所以select/find和key constraint錯誤都不是實際的db查詢的結果,而是基於已經載入緩存的數據計算Hibernate的結果。

塞巴斯蒂安

+0

我不完全知道如何做select/find upfront解決我的問題。我的應用程序的其他一些線程/節點仍然可以在選擇和插入之間插入衝突實體。 –

0

捕獲org.hibernate.JDBCException。這有getErrorCode()。對於獨特的約束voilation它的ORA-00001。

-Maddy

+0

ORA-00001是否與Oracle相關? –

0

如果有數據庫異常,它將被捕獲到HibernateException,這是一個檢查異常。 Spring將其包含在DataAccessException中,該選項未被選中。這個例外將運行到您的Controller並輸出到Servlet,並最終以瀏覽器和日誌文件中的堆棧跟蹤結束。您可以捕獲此異常並將其打印出來,以便查看正在發生的情況。這至少會讓你知道什麼是真正的突破。

壞鑰匙可能是一個問題。但不好的價值可能是另一回事。一些非空字段爲空,或者某些東西不夠長或足夠短等。修復這可能涉及驗證。您可以使用Hibernate Validator。你給你的領域一些漂亮的註釋,然後你在得到數據庫之前就會得到java驗證錯誤 - 錯誤發生得更快。