SaveOrUpdate跳过表

时间:2012-12-15 13:13:15

标签: java spring hibernate hbmxml

Hibernate V.4.1.8最终

Spring:3.1.3发布

场景:在客户注册过程中,用户将填写完整的。在最终确定表单之前,他可以多次保存表单,然后单击“提交”以完成内容。应用程序仅在最终提交后才会创建客户ID。 为了实现此功能,我基于相同的POJO创建了2个表。参考:Mapping same POJO to more than one table

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

请将custDetail对象的sql序列看到备份表和customer表中。

插入备份表

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但没有进展。即使我试图删除级联选项。

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

此致

希里什

1 个答案:

答案 0 :(得分:0)

您的约束是否立竿见影?让他们推迟。这样,hibernate可以在事务结束之前编写所有表而不会出现约束违规。

如果您正在使用MySQL,则无法将约束推迟到事务结束。然后,您必须确保始终在db中插入一致状态。对于你而言,这意味着重写一些代码,以便你有效地发出两个保存,一个只保存客户,另一个保存客户的家庭属性。

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

 custDetails.setStatus("A");

之上

// 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内部。如前所述,我建议使用两次保存。