2009-07-30 48 views
7

我正在研究大多數只讀的數據庫應用程序,但有一個表記錄用戶在應用程序中的移動並且有大量的寫入。對於每一個幾千寫道,我們看到在錯誤日誌中有一些例外,像這樣:從Hibernate獲取重複輸入錯誤,是MySQL責備?

[WARN][2009-07-30 11:09:20,083][org.hibernate.util.JDBCExceptionReporter] SQL Error: 1062, SQLState: 23000 
[ERROR][2009-07-30 11:09:20,083][org.hibernate.util.JDBCExceptionReporter] Duplicate entry '17011' for key 1 
[ERROR][2009-07-30 11:09:20,083][org.hibernate.event.def.AbstractFlushingEventListener] Could not synchronize database state with session 
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update 
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94) 
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) 
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) 

問題的表具有以下模式:

CREATE TABLE IF NOT EXISTS `my_table` (
    `id` int(11) NOT NULL, 
    `data1` int(11) NOT NULL, 
    `data2` int(11) NOT NULL, 
    `timestamp` datetime default NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; 

以及相應的Hibernate映射XML:

<hibernate-mapping> 
    <class name="mycorp.MyClass" table="my_table"> 
    <id name="id" column="id" type="java.lang.Integer"> 
     <generator class="increment"/> 
    </id> 
    <property name="data1" column="data1" type="java.lang.Integer"/> 
    <property name="data2" column="data2" type="java.lang.Integer"/> 
    <property name="timestamp" column="timestamp" type="java.util.Date"/> 
    </class> 
</hibernate-mapping> 

儘管不太可能,我們的Web應用程序的多個實例可能一次寫入數據庫,因爲我們在我們的webapp上下文中版本號以無縫釋放新v應用程序的版本。因此,在其Web瀏覽器中緩存應用程序的舊版本的客戶端將訪問服務器的舊版本,我們將在幾周後取消部署。無論如何,我不相信這是問題,但我懷疑MySQL和Hibernate之間存在一些同步問題。會改變我的發電機序列,seqhilo或希洛幫助?另外,如果你可以提供一個在MySQL中設置這樣一個生成器的例子,這將是非常有用的,因爲大部分在線資源都是從Hibernate手冊中極其簡單的例子中複製粘貼的。

回答

9

如果您有多個進程寫入同一個表 - 您肯定會發生衝突,但增量絕對不好。

既然是我們正在討論的MySQL,那麼最簡單的就是使用identity。在Hibernate映射:

<generator class="identity"/> 

在你的MySQL腳本:

CREATE TABLE IF NOT EXISTS `my_table` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `data1` int(11) NOT NULL, 
    `data2` int(11) NOT NULL, 
    `timestamp` datetime default NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; 

要變更現有的表:

ALTER TABLE `my_table` 
    CHANGE COLUMN `id` `id` int(11) NOT NULL AUTO_INCREMENT=$NEW_VALUE$; 

其中$ NEW_VALUE $應當由下一個可用的ID來代替,從而該序列不會重置爲1.

+0

非常徹底和明確的答案 - 謝謝! – 2009-07-31 13:18:16