【问题标题】:Hibernate mapping to object that already existsHibernate 映射到已经存在的对象
【发布时间】:2011-02-14 21:00:39
【问题描述】:

我有两个类,ServiceType 和 ServiceRequest。每个 ServiceRequest 都必须指定它是什么类型的 ServiceType。所有 ServiceType 都在数据库中预定义,ServiceRequest 由客户端在运行时创建。

这是我的 .hbm 文件:

<hibernate-mapping>
  <class dynamic-insert="false" dynamic-update="false" mutable="true" name="xxx.model.entity.ServiceRequest" optimistic-lock="version" polymorphism="implicit" select-before-update="false">
    <id column="USER_ID" name="id">
      <generator class="native"/>
    </id>
    <property name="quantity">
        <column name="quantity" not-null="true"/>
    </property>
    <many-to-one cascade="all" class="xxx.model.entity.ServiceType" column="service_type" name="serviceType" not-null="false" unique="false"/>
  </class>
</hibernate-mapping>

<hibernate-mapping>
  <class dynamic-insert="false" dynamic-update="false" mutable="true" name="xxx.model.entity.ServiceType" optimistic-lock="version" polymorphism="implicit" select-before-update="false">
    <id column="USER_ID" name="id">
      <generator class="native"/>
    </id>
    <property name="description">
        <column name="description" not-null="false"/>
    </property>
    <property name="cost">
        <column name="cost" not-null="true"/>
    </property>
    <property name="enabled">
        <column name="enabled" not-null="true"/>
    </property>
  </class>
</hibernate-mapping>

当我运行它时,我得到了

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails

我认为我的问题是,当我创建一个新的 ServiceRequest 对象时,ServiceType 是它的属性之一,因此当我将 ServiceRequest 保存到数据库时,Hibernate 尝试再次插入 ServiceType 对象,并发现它已经存在。如果是这种情况,我该如何让 Hibernate 指向存在的 ServiceType 而不是尝试再次插入它?

抛出错误的代码:

/* Get existing Service Type from database */
ServiceType st = DAOFactory.getDAOFactory().getServiceTypeDAO().getServiceType(newServiceTypeName);

/* Set the ServiceType of the new Service Request*/
newServiceRequest.setServiceType(st);

/* Error occurs inside this function which simply calls
    session.beginTransaction();
    session.save(sr);
    session.getTransaction().commit();  */
DAOFactory.getDAOFactory().getServiceRequestDAO().saveData(newServiceRequest);
return "newRequestDone";

【问题讨论】:

  • 您正在运行的导致该异常的代码是什么?
  • 当我尝试保存 ServiceRequest 时会发生这种情况。它只是一个简单的 session.beginTransaction(); session.save(sr); session.getTransaction().commit();

标签: hibernate mapping foreign-keys


【解决方案1】:

在没有导致异常的代码的情况下,我想说您的问题可能是您正在尝试为每个 ServiceRequest 创建一个新的 ServiceType 而您需要做的是检索现有的 @ 987654323@ 通过 id 而不是每次都添加一个新的。

如果这听起来不合理,请显示您的 java 代码,我会尽力帮助您:)


进一步帮助:您的 DAO 是否使用相同的休眠会话?从一个会话加载并保存在另一个会话中的实体可能会导致问题,除非您使用 merge 而不是 save

【讨论】:

  • 我更新了我的问题以显示代码。如您所见,我正在从数据库中请求 ServiceType,然后再次保存。
  • 是的,我为每个 DAO 使用相同的会话。
  • 你可以尝试 merge() 而不是 save() 吗?还是将整个事情封装在事务中?否则我没有想法,对不起。
  • 不,合并不能解决它:(。所以 Hibernate 会处理我保存数据库中已经存在的实体的情况(在我的例子中是 ServiceRequest 的属性 ServiceType)?
  • 不应该这样做。实际上还有一件事要尝试,去掉多对一映射中的 cascade="all" ,看看是否有帮助?
【解决方案2】:

您的 SQL 异常似乎与它试图创建一个已经存在的 ServiceType 的假设并不相符。您不希望在 ServiceType 表上看到唯一约束违规吗?看到这一点,我首先要检查的是,数据库中的 FK 目标是否与休眠映射匹配?当您的 ServiceType 实体指向 (BOB_DEV_SERVICE_TYPES) 但在 ServiceRequest 上强制执行的实际外键转到 (TINA_TEST_SERVICE_TYPES) 时,您可以获得类似的结果

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    相关资源
    最近更新 更多