当前位置: 首页 > 面试题库 >

休眠问题:外键的列数必须与引用的主键相同

魏誉
2023-03-14
问题内容

目标:我想在ImportJob中使用importJobId作为分配表ID的外键,这样,当我们那时具有importJobId时,那么我们只能在ID中分配ID,因为没有Job时就无法进行任何分配。

ImportJob表的复合主键为[ORGID,IMPORTJOBTYPE],正在尝试使用以下方式在休眠状态下创建外键关系:

  <id name="id"
        column="ID">
        <generator class="native"/>
    </id>
    <many-to-one name="importjobid"
                 class="com.delta.pdo.admin.ImportJob"
                 cascade="save-update"/>

在Allocation.hbm.xml中无法解决,并收到以下错误消息:

Foreign key (FKB29B5F7366007086:ALLOCATIONS [importjobid])) 
must have same number of columns as the 
referenced primary key (IMPORTJOBMANAGMENT [ORGID,IMPORTJOBTYPE])

这是我的ImportJob.hbm.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.delta.pdo.admin.ImportJob" table="IMPORTJOB" lazy="false">
        <!-- we don't cache this since the commissions code is too screwed up to work with -->
        <composite-id>
            <key-property name="orgId" type="long" column="ORGID"/>
            <key-property name="importJobType" type="java.lang.String" column="IMPORTJOBTYPE"/>
        </composite-id>

        <!-- Make sure importjobid is not-null='true '-->
        <property name="importjobid" type="long" column="IMPORTJOBID" />
        <property name="allocations" type="boolean" column="ALLOCATIONS" />
    </class>
</hibernate-mapping>

这是供参考的Bean类:

public class AllocationBean extends WorkbenchBeanBase
{
    private static final Logger log = Logger.getLogger(AllocationBean.class);
    private Float allocations;
    private String importJobType;
    private long id;
    private long orgId;
}

public class ImportJobManagment implements Serializable
{
    private long importjobid;
    private long orgId;
    private String importJobType;
    private boolean allocations = false;
}

getter/setter为了简单起见,我已将其删除。

更新:1
现在设置的方式,我在一个表中有id列,该列具有对orgId和importJobType的复合键的外键引用,不确定我们是否可以做到这一点,并且具有对另一复合键的单列外键表,但这是我的用例。

更新:2

感谢您提供的精妙细节,这肯定会使我对外键实现有所了解,但是我的最终目标是在两个表之间进行一对一映射,其中表A具有用于标识该表和表B中唯一行的复合键。具有主键,该主键具有对表A的外键引用,因此,如果我们在表A中具有条目,则同一jobId条目应在表B中,现在我明白了,我们不能在表B中具有单列主键来引用表A中的组合键。

所以基本上我想在表之间建立一对一的映射,其中表A具有复合主键,而表B具有单列主键,这是使用休眠方式,这当然会引起上述错误,所以现在我要在表中创建复合键现在,B还参考表A,因此我将稍后用我的发现验证并更新我的问题,再次感谢您的详细输入。


问题答案:

该错误说明一切,为了引用复合主键,您需要一个复合外键。(复合主键指出,您需要2个字段的唯一组合才能构成一个键-这样就不可能仅用1列引用一个唯一键。)

至于不确定如何通过使用xml映射文件来实现,目前大多数人都使用注释。

至于您的Java类,我假设ImportJobManagement拥有一个ImportJob,因此该类不应引用id,而应引用对象本身,如下所示:

public class ImportJobManagment implements Serializable {
    private ImportJob importJob;
    ...
}

Java类应该只引用其他类,而不是组合键的成员-取决于从组合键到Java成员变量的映射。

更新答案:

简短的答案是不,您不能。外键的工作方式,它使您可以引用表中的特定行。并且,为了确保引用特定行,您需要一个标识,该标识只能描述一行,而不能描述其他任何一行。在SQL中,有一个用于实现此目的的结构,即唯一键。通过声明一列(或列的组合)是唯一的,您知道其/它们的组合值将是唯一的,在整个表中此值最多为1行,否则将违反约束。

因此,外键指的是单个唯一约束列,或者是跨越多个列的复合唯一键。由于所有表都已经有一个唯一键,即主键(它始终是唯一的),通常将其用于外键引用,但是任何unqiue列都可以使用。

最简单的情况是当我们要引用具有单列唯一键的表时。两个简单表A,其中一个表包含一个“ id”列,另一个表B,其中包含一个“
id”列,另一个表a_id,具有对A的“ id”列的外键。情况可能是这样的:

A:
| id | 
|----|
|  1 |
|  2 |
|  3 |

B:
| id | a_id |
| 2  |  3   |
| 3  |  1   |

在这里,B中的每一行都引用A中的一行。它是直接引用,表B中a_id中的值直接对应于A’‘id’列中的值。因此,ID为2的B引用ID为3的A,依此类推。

现在让我们看一下如何使用复合唯一键引用表。让我们继续我们的示例,但是现在A具有另一列“ sec_id”,该列与“ id”一起组成了一个复合主键。

A:
| id | sec_id |
|----|--------|
| 1  |   3    |
| 3  |   1    |
| 3  |   7    |

B:
| id | a_id |
|----|------|
| 2  |  3   |

在这种情况下,我们在B中遇到了问题。由于外键必须引用其引用的表中的一行,因此这显然行不通。值“
3”代表A中的哪一行?第一行中的sec_id?第二个或第三个ID(但在那种情况下,哪个?)?答案当然不是,B中没有足够的信息来引用A中的单个行,因此SQL只是没有。因此,不允许添加此类外键。

为了让B引用A,它需要同时引用A的’id’列和A的’sec_id’列,因为A中的一行是由其唯一的(’id’,’sec_id’ )对。因此,B看起来像这样:

| id | a_id | a_sec_id |
|----|------|----------|
| 1  |  1   |     3    |
| 2  |  3   |     1    |
| 3  |  3   |     7    |

现在,B拥有足够的信息来引用A中的一行,并且如数据所示,它确实可以。

再次更新:

我目前正在阅读JPA认证,并且已经阅读了有关复合键映射的章节。为了映射复合主键,您需要一个主键类,该主键类映射您的键的属性。有两种实现方法,一种是键属性也必须映射到实体本身中,另一种是将其用作嵌入式键。

我将提供代码示例,它们很好地说明了自己(它使用的是注释,您也应该这样做)。

第一个示例是具有常规id类(未嵌入)的基本示例。在这里,我们有一个Employee实体,其中的主键由一个整数id和一个国家/地区组成(如果在不同的国家/地区,两名雇员可以具有相同的id)。

@Entity
@IdClass(EmployeeId.class)
public class Employee {
    @Id private String country
    @Id
    @Column(name = "EMP_ID")
    private int id;
    private String name;
    ...
}

public class EmployeeId implements Serializable {
    private String country;
    private int id;

    public EmployeeId() { }
    public EmployeeId(final String country, final int id) {
        this.country = country;
        this.id = id;
    }

    //getters for the properties

    public boolean equals(final Object other) {
    //must be implemented
    }

    public int hashCode() {
    //must be implemented
    }
}

注意:

  • 类上的@ IdClass-annotation。
  • id-class的两个属性也必须在实体中定义
  • id类必须实现equals和hashcode

可以完成此操作的另一种方法是通过嵌入式id类:

@Entity
public class Employee {
    @EmbeddedId
    private EmployeeId id;
    private String name;

    public Employee(final String country, final int id) {
        this.id = new EmployeeId(country, id);
    }

    public String getCountry() {
        return id.getCountry();
    }
}

@Embeddable
public class EmployeeId {
   private String country;
   @Column(name = "EMP_ID")
   private int id;

   //constructor + getters + equals +hashCode
}

注意:

  • 无需在实体中定义id属性
  • 要从实体获取id-class的属性,您需要从id-class获取它们

我更喜欢后者,因为它更紧凑并且不包含重复项,但是我不知道如何使用两者进行比较。



 类似资料:
  • 问题内容: 目标:我想在ImportJob中使用importJobId作为分配表ID的外键,这样,当我们那时具有importJobId时,那么我们只能在ID中分配ID,因为没有Job时就无法进行任何分配。 ImportJob表的复合主键为[ORGID,IMPORTJOBTYPE],正在尝试使用以下方式在hibernate状态下创建外键关系: 在Allocation.hbm.xml中无法解决,并收到

  • 我知道这个主题在这里讨论了很多次,但我仍然坚持一个例外:外键必须与引用的主键具有相同的列数。 (我正在使用spring数据和hibernate) 我的身份证类别: 我的实体: 对于这种构造,我得到以下例外情况: 导致:org.hibernate.MappingException:外键(FK_ad3h9gu4labg6ix34bei3poxt:proxy_dienst_关系[parent_diens

  • 我有一个实体,叫做FatRabbitCarrot: 而且很管用。现在上面的类已经替换了字段名,但是结构和我们的存储库是一样的。 然后我尝试添加一个新实体,该实体在上面的类中有一个外键。让我们把这门课叫做NutToffee。FatRabbitCarrot与这个新实体有一对一的关系,而实体本身应该有一对一的关系: 对我来说,这似乎是一个有效的类。但看起来不像。我们正在使用Java8、Hibernate

  • 我在实体和之间有多对多的关系,我使用了一个名为的关联表。 AbstractEntity.java: FunctionEntity.java: FunctionProduceResultEntity.java: ResultEntity.java 功能实用性: 启动服务器时,出现以下错误: 还有类似的问题,例如外键必须具有与多对一映射中引用的主键相同的列数,以及Hibernate MappingEx

  • 我有域类 - 用户、角色、组、组角色 用户域 用户.hbm.xml 我有user_grouprole表作为一个连接表为一个用户和一组分组程序我有user_role表作为一个连接表为一个用户和一组角色 组域 Group.hbm.xml 组角色 GroupRole.hbm.xml 当我尝试使用主类进行测试时,我得到了一个映射错误,比如Hibernate映射错误,比如外键(FK5110401A83989

  • 嗨,下面是我的实体,它们之间有许多联系 大学生JAVA 学生详细信息。JAVA appmain.java 下面是我的2表中的列 “学生详细信息”中的“值”应输入学生表的“用户角色” 但当我执行appmain时,我的错误率就降低了 我试图解决这个问题,但它显示出同样的错误请建议我如何解决这个问题