0

休眠 V.4.1.8 最终版

春季:3.1.3 发布

场景:在客户注册过程中,用户将填写完整的来自。他可以在完成表单之前多次保存表单,然后单击提交以完成内容。只有在最终提交后,应用程序才会创建客户 ID。为了实现这个功能,我创建了 2 个基于相同 POJO 的表。参考: 将同一个 POJO 映射到多个表

问题: 将数据保存到客户表中时。hibernate 将记录插入地址表并直接插入家庭表,但忽略客户表。因此抛出异常:无法添加或更新子行:外键约束失败

请在 custDetail 对象进入备份表和客户表时查看 sql 序列。

插入备份表

Hibernate: insert into mypack.address_bk (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into mypack.address_bk (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into mypack.address_bk (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into mypack.customer_bk (version, custId, custBirthDate, custEducation, custFirstName, custGender, custLastName, custMiddleName, custTitle, exServiceManFlag, fatherFullName, handicappedFlag, motherFullName, staffFlag, status, userId, bankCode, branchCode, customerPhoto, currentAddress, permanentAddress, officeAddress) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into mypack.family_bk (custId, memberName, relation, birthDate, gender, occupation) values (?, ?, ?, ?, ?, ?)

插入客户表

Hibernate: insert into mypack.address (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into mypack.address (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into mypack.address (address1, address2, city, emailAddress, faxNo, landLineNo, mobileNo, pincode, state, verified) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into mypack.family (custId, memberName, relation, birthDate, gender, occupation) values (?, ?, ?, ?, ?, ?)
SQL Error: 1452, SQLState: 23000 Cannot add or update a child row: a foreign key constraint fails

表定义:

<class entity-name="com.boss.mypack.model.Customer" lazy="true"
    name="com.boss.mypack.model.Customer" polymorphism="explicit"
    schema="mypack" table="customer">
    <id length="15" name="custId" type="string">
        <column length="20" name="custId" />
        <generator class="assigned" />
    </id>
    <version column="version" generated="never" name="version"
        type="integer" unsaved-value="null" />
    <property generated="never" lazy="false" name="tempId" type="java.lang.Integer"> 
        <column name="tempId" not-null="false" /> 
    </property>
    <many-to-one cascade="all" class="com.boss.mypack.model.Address"
        entity-name="com.boss.mypack.model.Address" fetch="select" lazy="false"
        name="OfficeAddress">
        <column name="officeAddress" />
    </many-to-one>
    <set cascade="all" fetch="select" inverse="true" lazy="true" name="family"
        sort="unsorted" table="family">
        <key>
            <column length="20" name="custId" />
        </key>
        <one-to-many class="com.boss.mypack.model.Family"
            entity-name="com.boss.mypack.model.Family" />
    </set>
</class>

后桌:

<class entity-name="bkCustomer" lazy="true"
    name="com.boss.mypack.model.Customer" polymorphism="explicit"
    schema="mypack" table="customer_bk">
    <id length="4" name="tempId" type="java.lang.Integer">
        <column length="20" name="tempId" />
        <generator class="identity" />
    </id>
    <version column="version" generated="never" name="version"
        type="integer" unsaved-value="null" />
    <property generated="never" lazy="false" name="custId" type="string">
        <column length="20" name="custId" />
    </property>
    <many-to-one cascade="all" class="com.boss.mypack.model.Address"
        entity-name="bkAddress" fetch="select" lazy="false" name="OfficeAddress">
        <column name="officeAddress" />
    </many-to-one>
    <set cascade="all" fetch="select" inverse="true" lazy="true" name="family"
        sort="unsorted" table="bkfamily">
        <key>
            <column length="20" name="custId" />
        </key>
        <one-to-many class="com.boss.mypack.model.Family"
            entity-name="bkFamily" />
    </set>
</class>

保存方法:

public void saveCustomer(Customer custDetails) {
    Session session;
    session = getSessionFactory().getCurrentSession();  
    session.beginTransaction();

    try {
        session.saveOrUpdate("bkCustomer", custDetails);
        session.getTransaction().commit();
    } catch (Exception e) {
        session.getTransaction().rollback();
        e.printStackTrace();
    }
}

批准客户方法

@Override
public void approveCustomer(Customer custDetails) {
    Session session = null;
    // Saving Customer details to Database
    try {
        //TODO:Need to this in single session, In failure, every changes should get rolled back.
        //Removing from backup Table
        session = getSessionFactory().getCurrentSession();  
        session.beginTransaction();
        session.delete("bkCustomer", custDetails);
        session.getTransaction().commit();
        System.out.println("**** Record Deleted ****");

        session = getSessionFactory().getCurrentSession();  
        session.beginTransaction();

        // check to see whether this is new customer.
        if (custDetails.getCustId() == null) {
            // New Customer - Generate Customer ID
            custDetails.setTempId(null);
            custDetails.setCustId(getNextCustomerCode(session));

            // Clear all Auto Generated IDs
            custDetails.getCurrentAddress().setAddressId(null);
            custDetails.getOfficeAddress().setAddressId(null);
            custDetails.getPermanentAddress().setAddressId(null);
            // custDetails.getPhotoMaster().setPhotoId(0);

            Set<Family> familyMembers = custDetails.getFamily();

            for (Family member : familyMembers) {
                member.setMemberId(null);
            }
        } else {
            System.out.println("**** This customer is already present in Database");
        }

        custDetails.setStatus("A");

        session.saveOrUpdate("com.boss.mypack.model.Customer", custDetails);

        //Following works properly, updates Backup tables
        //session.saveOrUpdate("bkCustomer", custDetails);

        session.getTransaction().commit();

        // Saving Customer details to LDAP.
        // ldapDAO.saveOrUpdate(custDetails);
        // session.getTransaction().commit();
    } catch (Exception e) {
        session.getTransaction().rollback();
        e.printStackTrace();
    }
}

我在客户表上没有任何异常。我尝试使用 session.clear/flash/evict/merge/replicate 等分离对象,使用 DOZER 但没有进展。即使我试图删除级联选项。

我不确定哪里出了问题。请帮忙。

问候,

希里什语

4

1 回答 1

0

你的限制是即时的吗?让他们推迟。这样,hibernate 可以在事务结束之前写入所有表而不会违反约束。

如果您使用 MySQL,则不能将约束推迟到事务结束。然后,您必须确保始终将一致的状态插入到数据库中。对您来说,这意味着重写一些代码,以便您有效地发出两次保存,一次只保存客户,另一种保存具有家庭属性的客户。

无论如何,有趣的是找出为什么 Hibernate 尝试首先插入族,而在 bk 表上插入的顺序符合预期。只是一个猜测:尝试移动语句

 custDetails.setStatus("A");

在 if 块之上

// check to see whether this is new customer.
    if (custDetails.getCustId() == null) {
        // New Customer - Generate Customer ID
        custDetails.setTempId(null);
        custDetails.setCustId(getNextCustomerCode(session));

        // Clear all Auto Generated IDs
        custDetails.getCurrentAddress().setAddressId(null);
        custDetails.getOfficeAddress().setAddressId(null);
        custDetails.getPer...

这样,Hibernate 可能会重新排序插入,因为 family 是最后编辑的实体,并且您的代码将起作用。无论如何,这将严重依赖于 Hibernate 内部。如前所述,我建议使用两次保存。

于 2012-12-15T20:31:14.080 回答