【问题标题】:Hibernate not setting foreign key on insert休眠未在插入时设置外键
【发布时间】:2013-03-06 04:42:30
【问题描述】:

我有多对一的关系,当我尝试插入一个值时,没有传递前键。 hibernate 不会在生成的 SQL 查询中包含它的值。

City 和 LocalizedLocation 实体的定义:

<!-- LocalizedLocation -->
 <hibernate-mapping>
   <class name="servicedb.dal.domain.LocalizedLocation" table="localized_location" catalog="DB">
     <composite-id name="id" class="servicedb.dal.domain.LocalizedLocationId">
     <key-property name="localeId" type="int">
       <column name="locale_id" />
     </key-property>
     <key-property name="locationId" type="int">
       <column name="location_id" />
     </key-property>
     </composite-id>
    <many-to-one name="location" class="servicedbcedb.dal.domain.Location" update="false" insert="false" fetch="select">
   <column name="location_id" not-null="true" />
 </many-to-one>
 <many-to-one name="city" class="servicedb.dal.domain.City" update="false" insert="false" fetch="select" cascade="all">
     <column name="locale_id" not-null="true" />
     <column name="country_code" length="2" not-null="true" />
     <column name="city_id" not-null="true" />
     </many-to-one>    
        <property name="title" type="string">
     <column name="title" length="120" />
     </property>
   </class>
 </hibernate-mapping>

 <!-- City -->
 <hibernate-mapping>
   <class name="servicedb.dal.domain.City" table="city" catalog="DB">
     <composite-id name="id" class="servicedb.dal.domain.CityId">
     <key-property name="localeId" type="int">
       <column name="locale_id" />
     </key-property>
     <key-property name="countryCode" type="string">
       <column name="country_code" length="2" />
     </key-property>
     <key-property name="id" type="int">
       <column name="id" />
     </key-property>
     </composite-id>
     <property name="name" type="string">
     <column name="name" length="100" not-null="true" />
     </property>
     <set name="localizedLocations" table="localized_location" inverse="true" lazy="true" fetch="select">
     <key>
       <column name="locale_id" not-null="true" />
       <column name="country_code" length="2" not-null="true" />
       <column name="city_id" not-null="true" />
     </key>
     <one-to-many class="servicedb.dal.domain.LocalizedLocation" />
     </set>
   </class>
 </hibernate-mapping>

下面的代码应该先插入Location,然后再插入LocalizedLocation,LocalizedLocation应该有指向插入Location的外键,但由于某种原因它没有。

Session session = locationDAO.getSession();
session.beginTransaction();

// Location inititalization, the object is correctly populated
session.save(location);

LocalizedLocation localizedLocation = new LocalizedLocation();
localizedLocation.setId(new LocalizedLocationId(locale.getId(), location.getId()));

localizedLocation.setCity(city); // the city already exists on the database, object is not null
localizedLocation.setLocale(locale); // the locale already exusts on the database
localizedLocation.setLocation(location);

session.save(localizedLocation);
session.getTransaction().commit();

提交后,生成的插入查询如下:

insert into DB.localized_location (title, description, locale_id, location_id)  values (?, ?, ?, ?)

但应该是:

insert into DB.localized_location (title, description, locale_id, location_id, city_id, country_code)  values (?, ?, ?, ?, ?, ?)

有人知道为什么生成的sql插入语句中没有包含city表的外键吗?

我也在使用 eclipse 和 reveng.xml 对数据库进行逆向工程,所以我的 hbm 文件是自动生成的,我没有使用 EJB3 注释。

【问题讨论】:

  • 你找到解决方案了吗?
  • 帮助@JoshC。我试图通过多个表属性重用 locale_id。我不知道为什么 Hibernate 不喜欢它,但由于某种原因,它没有在插入时填充 FK。为了解决这个问题,我为 LocaleId 创建了一个附加属性。因此,locale_id 一直作为 Location Table 的 PK,而附加属性 locale_city_id 成为 City Table 的 FK。两个属性始终具有相同的值(这由 DAL 逻辑保证)。使用所描述的方法,您将在数据库中获得冗余信息,我不知道是否有更好的解决方案。

标签: hibernate orm foreign-keys mapping reverse-engineering


【解决方案1】:

LocalizedLocation 映射中的 city 属性似乎具有“insert=false”和“update=false”。以这种方式映射,它使其成为“反向”关系,其中仅从另一端保存连接 - 即在保存位置时。

要么删除这两个属性,要么在建立关系后保存城市。

编辑:更正了属性。

顺便说一句,如果城市没有映射 LocalizedLocations 列表 - 因为我不知何故从你的描述中得到了这个想法 - 将这两个属性设置为 false 似乎没有意义,因为插入这种关系的唯一方法是在同一列上映射另一个属性(或直接在数据库上进行)。

【讨论】:

  • 我不确定我是否理解您的建议。 location_id 已正确发布,缺少的值为来自localized_location 的 city_id 和 country_code。
  • 抱歉,我放错了属性名称,但同样的概念也适用于 city,因为您在 false 处有“更新”和“创建” i> 那里也是如此。为了清楚起见,我会更新答案,但建议几乎相同,只是关于“城市”关系。
  • 我尝试了两种方法,删除插入和更新属性并在建立关系后保存城市。但是外键仍然丢失。
  • 顺便说一句,当同时删除“更新”和“创建”属性时,我收到以下异常:原因:org.hibernate.MappingException:实体映射中的重复列:guideme.servicedb。 dal.domain.LocalizedLocation 列:locale_id(应使用 insert="false" update="false" 映射)
猜你喜欢
  • 2021-06-15
  • 2012-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多