【问题标题】:hibernate composite key休眠复合键
【发布时间】:2010-02-20 06:03:14
【问题描述】:

是否需要将composite-id映射到类??

可以这样吗?

<composite-id>
  <key-property=..../>
  <key-property=..../>
</composite-id>

或者应该是

<composite-id class=....>
  <key-property=..../>
  <key-property=..../>
</composite-id>

如果我们有复合键,那么该类是否应该实现equals()override() 方法?

【问题讨论】:

    标签: java hibernate composite-key


    【解决方案1】:

    Hibernate 需要能够比较和序列化标识符。所以标识符类必须是可序列化的,并且覆盖 hashCode() 和 equals() 与数据库的复合键相等概念一致。

    如果您将复合 id 映射为实体的属性,则实体本身就是标识符。

    第二种方法称为映射复合标识符,其中在 元素内命名的标识符属性在持久类和单独的标识符类上都重复

    最后,composite-id 可能是一个组件类。在这种情况下,组件类是标识符类。

    请注意,强烈建议将 ID 设置为单独的类。否则你将只有非常尴尬的方式来使用 session.get() 或 session.load() 来查找你的对象。

    参考文档的相关部分:

    在此示例中,复合 ID 被映射为实体的属性。 (以下假设您正在定义 Employee 类)。

    <composite-id>
        <key-property name="EmployeeNumber"/>
        <key-property name="Dependent"/>
    </composite-id>
    
    class EmployeeAssignment implements Serializable
    {
        string getEmployeeNumber()
        void setEmployeeNumber( string value )
        string getDepartment()
        void setDepartment( string value )
        boolean equals( Object obj )
        int hashCode()
    }
    

    一个映射的复合ID:

    <composite-id class="EmployeeAssignmentId" mapped="true">
        <key-property name="EmployeeNumber"/>
        <key-property name="Dependent"/>
    </composite-id>
    
    class EmployeeAssignment
    {
        string getEmployeeNumber()
        void setEmployeeNumber( string value )
        string getDepartment()
        void setDepartment( string value )
    }
    
    class EmployeeAssignmentId implements Serializable
    {
        string getEmployeeNumber()
        void setEmployeeNumber( string value )
        string getDepartment()
        void setDepartment( string value )
        boolean equals( Object obj )
        int hashCode()
    }
    

    作为复合ID的组件:

    <composite-id name="Id" class="EmployeeAssignmentId">
        <key-property name="EmployeeNumber"/>
        <key-property name="Dependent"/>
    </composite-id>
    
    class EmployeeAssignment
    {
        EmployeeAssignmentId getId()
        void setId( EmployeeAssignmentId value )
    }
    
    class EmployeeAssignmentId implements Serializable
    {
        string getEmployeeNumber()
        void setEmployeeNumber( string value )
        string getDepartment()
        void setDepartment( string value )
        boolean equals( Object obj )
        int hashCode()
    }
    

    【讨论】:

    • 令人困惑的例子。另外,复合ID中的“依赖”是什么?你的意思是把'部门'?无论哪种方式,仍然是一个令人困惑的例子。可以通过 cmets 来解释来澄清。
    • 如果让实体本身作为标识符,是不是意味着equals和hashcode只能使用复合ID的to而不能使用任何其他字段来检查相等性?
    【解决方案2】:

    两者都是可能的。如果你使用

    <composite-id>
      <key-property=..../>
      <key-property=..../>
    </composite-id>
    

    然后不需要单独的类来表示密钥。 ID 值取自实体本身的属性。

    如果你使用

    <composite-id class="....">
      <key-property=..../>
      <key-property=..../>
    </composite-id>
    

    然后指定的类将用作关键属性的持有者。但是,实体类必须具有这些属性 - 值存储在实体类和复合 ID 类中。实体类不知道键类。在我看来不是很好。

    在文档here 中描述了一种更好的第三种方法:

    <composite-id name="id" class="OrderLineId">
        <key-property name="lineId"/>
        <key-property name="orderId"/>
        <key-property name="customerId"/>
    </composite-id>
    

    这里,复合键由类OrderLineId表示,其实例存储在实体类中的字段id下。这使实体和键之间的分离更加清晰。

    【讨论】:

    • "If you use" ...你的意思是在该行之后添加一些代码吗?
    • 404 在您的文档链接上。
    【解决方案3】:

    如果您有一个包含与其他实体的关系的复合键,请这样做:

    <composite-id>
        <key-many-to-one name="employee" column="FK_EMPLOYEE" entity-name="net.package.name.Employee" />
        <key-many-to-one name="department" column="FK_DEPARTMENT" entity-name="net.package.name.Department" />
    </composite-id>
    

    【讨论】:

    • 很遗憾不起作用,抛出映射异常:Repeated column in mapping for entity
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-11
    相关资源
    最近更新 更多