【问题标题】:Getting duplicate entry errors from Hibernate, is MySQL to blame?从 Hibernate 得到重复的条目错误,是 MySQL 的罪魁祸首吗?
【发布时间】:2010-11-15 09:35:23
【问题描述】:

我正在开发一个主要是只读的数据库应用程序,但是有一个表记录了用户在应用程序中的移动,并且有大量的写入操作。对于每几千次写入,我们会在错误日志中看到一些异常,如下所示:

[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>

虽然不太可能,但我们的 webapp 的多个实例可能会同时写入数据库,因为我们在 webapp 上下文中版本号以无缝发布应用程序的新版本。因此,在其 Web 浏览器中缓存了旧版本应用程序的客户端将访问旧版本的服务器,我们会在几周后取消部署。

无论如何,我不相信这是问题所在,但我怀疑这里的 MySQL 和 Hibernate 之间存在一些同步问题。将我的生成器更改为序列、seqhilo 或 hilo 有帮助吗?另外,如果您能提供一个在 MySQL 中设置此类生成器的示例,那将非常有帮助,因为大多数在线资源都是从 Hibernate 手册中可悲的极简示例中简单复制粘贴的。

【问题讨论】:

    标签: mysql hibernate mysql-error-1062


    【解决方案1】:

    如果您有多个进程写入同一张表,那么增量绝对是不好的——您肯定会发生冲突。

    既然我们说的是 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。

    【讨论】:

      猜你喜欢
      • 2015-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-14
      • 1970-01-01
      • 1970-01-01
      • 2012-05-23
      相关资源
      最近更新 更多