【问题标题】:Hibernate 4: Partial many-to-one association + where/filter discriminatorHibernate 4:部分多对一关联 + where/filter 鉴别器
【发布时间】:2012-10-21 06:19:39
【问题描述】:

我正在使用 Hibernate 4。我有这个包含 Category 和 CategoryItem 表的数据库:

CREATE  TABLE `test`.`Category` (
  `Id` INT NOT NULL AUTO_INCREMENT ,
  `Description` VARCHAR(50) NOT NULL ,
  PRIMARY KEY (`Id`) )

CREATE  TABLE `test`.`CategoryItem` (
  `IdCategory` INT NOT NULL ,
  `Id` VARCHAR(10) NOT NULL ,
  `Description` VARCHAR(100) NOT NULL ,
  PRIMARY KEY (`Id`, `IdCategory`) ,
  CONSTRAINT `fk_table1_Category1`
    FOREIGN KEY (`IdCategory` )
    REFERENCES `test`.`Category` (`Id` ))

这用于存储不同的类别或目录及其值。例如:

分类表:

1, 'Genders'
2, 'Marital status'
3, 'Countries'

CategoryItem 表:

1, 'FEM', 'Female'
1, 'MAL', 'Male'
2, 'SIN', 'Single'
2, 'MAR', 'Married'
3, 'US', 'United States'
3, 'UK', 'England'

这些值在整个架构中使用,但仅对 CategoryItem(Id) 进行逻辑引用,例如:

CREATE  TABLE `test`.`Person` (
  `Id` INT NOT NULL ,
  `Name` VARCHAR(30) NULL ,
  --this fields are referencing CategoryItem(Id)
  `IdGender` VARCHAR(10) NOT NULL ,
  `IdMaritalStatus` VARCHAR(10) NOT NULL ,
  `IdCountryOrigen` VARCHAR(10) NOT NULL ,
  PRIMARY KEY (`Id`) )

是否可以在 Hibernate 中使用一些技术来映射这些表?我现在无法更改此架构。

已编辑:

这些是目前的类和映射:

public class Category implements Serializable {

    private int id;
    private String description;

    private Set<CategoryItem> items = new HashSet<CategoryItem>();

    public Category() {
    }

    //getters and setters omitted
}

public class CategoryItem implements Serializable {

    private CategoryItemId id;
    private Category category;
    private String description;

    public CategoryItem() {
    }
    //getters and setters omitted
}

public class CategoryItemId implements Serializable {

    private Category category;
    private String id;

    public CategoryItemId() {
    }
    //getters and setters omitted
}

public class Person implements Serializable {

    private int id;
    private String name;
    private CategoryItem gender;
    private CategoryItem maritalStatus;
    private CategoryItem countryOrigen;

    public PersonaNatural() {
    }
    //getters and setters omitted
}

  <class catalog="test" name="test.Category" table="Category">
    <id name="id" type="int">
      <column name="Id"/>
      <generator class="increment"/>
    </id>
    <property name="description" type="string">
      <column length="50" name="Description" not-null="true"/>
    </property>
    <set inverse="true" name="items">
      <key>
        <column name="IdCategory" not-null="true"/>
      </key>
      <one-to-many class="test.CategoryItem"/>
    </set>    
  </class>

  <class catalog="test" name="test.CategoryItem" table="CategoryItem">
    <composite-id class="test.CategoryItemId" name="id">
        <key-many-to-one name="category" class="test.Category">
            <column name="IdCategory" not-null="true"/>
        </key-many-to-one>
      <key-property name="id" type="string">
        <column name="Id"/>
      </key-property>
    </composite-id>
    <many-to-one name="category" class="test.Category" fetch="select" insert="false" update="false">
      <column name="IdCategory" not-null="true"/>
    </many-to-one>
    <property name="description" type="string">
      <column name="Description" length="100" not-null="true"/>
    </property>
  </class>

<class catalog="test" name="test.Person" table="Person">
    <id name="id" type="int">
      <column name="Id"/>
      <generator class="increment"/>
    </id>
    <property name="name" type="string">
      <column length="30" name="Name" not-null="false"/>
    </property>
    <many-to-one name="gender" class="test.CategoryItem" fetch="select">
        <column name="IdGender" not-null="true"/>
    </many-to-one>
    <many-to-one name="maritalStatus" class="test.CategoryItem" fetch="select">
        <column name="IdMaritalStatus" not-null="true"/>
    </many-to-one>
    <many-to-one name="countryOrigen" class="test.CategoryItem" fetch="select">
        <column name="IdCountryOrigen" not-null="true"/>
    </many-to-one>
  </class>

我正在尝试多对一,但我收到此错误:'must have the same number of columns as the referenced primary key'。这是有道理的,因为我假装只在 Person.hbm.xml 上映射 CategoryId(Id)。

我需要指定一个 wherediscriminator 值来完成左连接条件,因为 CategoryItem(Id) 本身并不是唯一的。

也许这对于 Hibernate 来说甚至是不可能的,但我将不胜感激。 谢谢。

【问题讨论】:

  • 如果您想让我们告诉您它们有什么问题,您应该向我们展示您的类及其映射。
  • 谢谢@JBNizet,我已经用类和映射文件编辑了我的问题。
  • 如果类别项的ID足以唯一标识一个项,那么它应该构成表的主键,以及实体的ID。如果这还不够,那么您应该在 Person 表中有两列来引用性别,另外两列来引用国家,还有另外两列来引用婚姻状况。照原样,您的架构没有多大意义。我强烈建议使用单列代理 ID。
  • 我同意@JBNizet 的观点,我只需要对这个模式进行编码,因为这是客户的要求;我将向团队公开在 CategoryItem 表上添加一个新列作为代理 Id 的替代方法。非常感谢您的帮助!
  • 正如我所说,如果这个架构有意义,则意味着项目 ID 是唯一的,因此可以用作 Hibernate ID。

标签: hibernate many-to-one discriminator


【解决方案1】:

这就是我解决 Person 映射的方法:

<class catalog="test" name="test.Person" table="Person">
    <id name="id" type="int">
      <column name="Id"/>
      <generator class="increment"/>
    </id>
    <property name="name" type="string">
      <column length="30" name="Name" not-null="false"/>
    </property>
    <many-to-one name="gender" class="test.CategoryItem" fetch="select">
        <formula>1</formula>
        <column name="IdGender" not-null="true"/>
    </many-to-one>
    <many-to-one name="maritalStatus" class="test.CategoryItem" fetch="select">
        <formula>2</formula>
        <column name="IdMaritalStatus" not-null="true"/>
    </many-to-one>
    <many-to-one name="countryOrigen" class="test.CategoryItem" fetch="select">
        <formula>3</formula>
        <column name="IdCountryOrigen" not-null="true"/>
    </many-to-one>
  </class>

添加 &lt;formula&gt;(IdCategory)&lt;/formula&gt; 而不是 &lt;column&gt; 元素会导致休眠匹配 CategoryItem 的复合 Id 并正确解析左连接。

谢谢。

【讨论】:

    猜你喜欢
    • 2011-12-20
    • 1970-01-01
    • 2015-01-26
    • 2020-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 2021-02-16
    相关资源
    最近更新 更多