【问题标题】:Hibernate primary key violation on two server instances两个服务器实例上的休眠主键冲突
【发布时间】:2017-04-23 04:11:58
【问题描述】:

我有一个在两台服务器上运行的应用程序,这两台服务器都通过 Hibernate 访问同一个数据库。 这里的问题是当这两个应用程序处理大量数据并尝试插入同一个表时。发生主键违规。从我注意到的事情来看,hibernate 似乎缓冲了一些主键 ID。例如。如果服务器 A 将数据插入到 id 100 中,同时服务器 B 将插入到 id 200 左右。我想这个问题与上述情况有关。以下是我的休眠属性

        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/dbtest?autoReconnect=true</property>

    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">password</property>
    <!--        <property name="hibernate.show_sql">true</property>-->
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <!-- 
    <property name="hibernate.hbm2ddl.auto">update</property>
     -->
    <property name="hibernate.use_sql_comments">true</property>
    <property name="hibernate.format_sql">true</property>
    <property name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property>
    <property name="hibernate.connection.isolation">2</property>
    <property name="hibernate.default_schema">dbtest</property>
    <property name="hibernate.jdbc.batch_size">50</property>
    <!--c3po connection pooling  -->
    <property name="hibernate.c3p0.min_size">5</property>
    <property name="hibernate.c3p0.max_size">20</property>
    <property name="hibernate.c3p0.timeout">300</property>
    <property name="hibernate.c3p0.max_statements">50</property>
    <property name="hibernate.c3p0.idle_test_period">3000</property>

这是失败的实体

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 3, 2014 4:38:39 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.test.dto.AdditionalContacts" table="additional_contacts"
           entity-name="additionalcontacts">
        <id name="contactId" type="java.lang.Integer" column="contactId">
            <generator class="increment" />
        </id>
        <property name="contactGuid" type="java.lang.String">
            <column name="contactGuid" />
        </property>
        <property name="contactName" type="java.lang.String">
            <column name="contactName" />
        </property>
        <property name="salutation" type="java.lang.String">
            <column name="salutation" />
        </property>
        <property name="EmailAddress" type="java.lang.String">
            <column name="email" />
        </property>
        <property name="includeInEmails" type="java.lang.Boolean">
            <column name="includeInEmails" />
        </property>
        <property name="Website" type="java.lang.String">
            <column name="website" />
        </property>
        <property name="city" type="java.lang.String">
            <column name="city" />
        </property>
        <property name="state" type="java.lang.String">
            <column name="state" />
        </property>
        <property name="postCode" type="java.lang.String">
            <column name="postCode" />
        </property>
        <property name="country" type="java.lang.String">
            <column name="country" />
        </property>
        <property name="street" type="java.lang.String">
            <column name="street" />
        </property>
        <property name="streetLine1" type="java.lang.String">
            <column name="streetLine1" />
        </property>
        <property name="streetLine2" type="java.lang.String">
            <column name="streetLine2" />
        </property>
        <property name="streetLine3" type="java.lang.String">
            <column name="streetLine3" />
        </property>
        <property name="streetLine4" type="java.lang.String">
            <column name="streetLine4" />
        </property>
        <property name="phone1" type="java.lang.String">
            <column name="phone1" />
        </property>
        <property name="phone2" type="java.lang.String">
            <column name="phone2" />
        </property>
        <property name="phone3" type="java.lang.String">
            <column name="phone3" />
        </property>
        <property name="fax" type="java.lang.String">
            <column name="fax" />
        </property>
        <property name="location" type="java.lang.String">
            <column name="location" />
        </property>
        <property access="field" column="createDate" insert="true"
                  name="createDate" update="false" />
        <property access="field" column="modifyDate" insert="true"
                  name="modifyDate" update="true" />
    </class>
</hibernate-mapping>

以下是使用上述实体的实体

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Sep 3, 2014 4:38:39 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.test.dto.Contacts" table="contact"
           entity-name="contact">
        <id name="cGuid" type="java.lang.String">
            <column name="contactGuid" />
        </id>
        <property name="org" type="java.lang.Integer">
            <column name="org" />
        </property>
        <property name="Name" type="java.lang.String">
            <column name="name" />
        </property>
        <property name="FirstName" type="java.lang.String">
            <column name="firstName" />
        </property>
        <property name="LastName" type="java.lang.String">
            <column name="lastName" />
        </property>
        <property name="abn" type="java.lang.String">
            <column name="abn" />
        </property>
        <property name="active" type="java.lang.Boolean">
            <column name="active" />
        </property>
        <property access="field" column="createDate" insert="true"
                  name="createDate" update="false" />
        <property access="field" column="modifyDate" insert="true"
                  name="modifyDate" update="true" />

        <bag name="additionalContactList" table="additional_contact" lazy="false" inverse="true"
             cascade="all">
            <key>
                <column name="contactGuid" not-null="true" />
            </key>
            <one-to-many entity-name="additionalcontacts"
                         class="com.test.dto.AdditionalContact" />
        </bag>
    </class>
</hibernate-mapping>

这个失败了

cascade="全部"

【问题讨论】:

  • 请为您要插入的对象添加 Hibernate 映射
  • 插入的是什么ID?
  • 你的 ID 生成策略是什么?
  • 嗨@Adam我更新了我的问题
  • @diufanman 是mysql原生id生成策略

标签: java hibernate


【解决方案1】:

您需要使用AUTO_INCREMENT。这样 MySQL 将管理 ID 的创建,因此服务器不必同步。将 DB 列更改为 AUTO_INCREMENT。在 Hibernate 中将生成器类型更改为 native

其他替代方法是使用 UUID 作为主键。

较新版本的 Hibernate 有其他可以使用的生成器,它们比 native 更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-12
    相关资源
    最近更新 更多