目标:我想有importJobId在ImportJob作为分配表的ID外键,这样当我们有importJobId然后再只有我们可以在分配ID为没有工作不能有任何分配。
ImportJob表有复合主键[ORGID,IMPORTJOBTYPE],我试图让使用建立在Hibernate外键关系
<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
谢谢你真棒细节,这肯定会enchance我的外键实现的知识,但我的最终目标是要一到两个表,其中表A具有识别该表和表B中唯一的行组合键之间的一个映射,我想有这将有外键引用表的主键一个这样的,如果我们在表格中的条目,则同样的jobId条目应在表B,现在我明白你的意思,我们不能有表B中单列主键,将参考在表A组合键
所以基本上我想有一个对表之间的一个映射,其中表A具有复合主键和表B具有使用休眠单个列主键,这是ofcourse我得到所提到的错误,因此现在我将创建在表复合键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,其中有一个外键“ID” A的这方面的一个实例列情况可能是这样的:
A:
| id |
|----|
| 1 |
| 2 |
| 3 |
B:
| id | a_id |
| 2 | 3 |
| 3 | 1 |
在此,在B参考各行中A.它的一个行的直接引用,在表B中A_ID值直接对应于A”的‘id’列中的值。 因此,与ID 2参考ID为3的A,等在B。
现在,让我们看看如何引用一个表有复合唯一键。 让我们保持我们的例子,但现在有另一列“sec_id”,这与“ID”共同构成一个复合主键。
A:
| id | sec_id |
|----|--------|
| 1 | 3 |
| 3 | 1 |
| 3 | 7 |
B:
| id | a_id |
|----|------|
| 2 | 3 |
在这种情况下,我们有一个自外键必须在它的引用,这显然行不通引用表中的一行B.一个问题。 这行中的确实值“3”代表什么? 第一行中的sec_id? 在id第二或第三(但是在这种情况下,哪一个?)? 答案当然是既不,没有足够的信息,在B到引用一个单行,所以SQL就不会拥有它。 增加这样一个外键因此不允许的。
为了使B到基准的,这将需要两个参考到A的“id'柱,和A的‘sec_id’列,因为在一个单排通过其唯一的(的组合来标识” ID”,‘sec_id’ )对。 因此,为B这样看:
| id | a_id | a_sec_id |
|----|------|----------|
| 1 | 1 | 3 |
| 2 | 3 | 1 |
| 3 | 3 | 7 |
现在,B保持足够的信息。在引用的单个行,并在将数据显示,它的作用。
再次更新:
目前,我正在阅读JPA认证,并已就复合键映射的章节。 为了映射复合主键,你需要它映射你的关键的属性的主键类。 有两种方法做的,其中一个关键属性还必须在实体本身映射,以及一个使用它的作为嵌入式密钥。
我提供的代码示例,他们很为自己说话(它的使用说明,你真正应该做的这一点。)
第一个例子是基座例如,与常规的ID级(未嵌入)。 在这里,我们在那里的主键是由一个整数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的注释。
- 无论是ID-类的属性还必须在实体定义
- 在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类的属性,你需要从ID级让他们
我喜欢,因为它更紧凑,后者更好,并且不包含重复的,但话又说回来,我不知道如何使用这两个比较..
ImportJob.hbm.xml
使用此一个增加insert = false
以importjobid像波纹管:
<property name="importjobid" type="long"
column="importjobid" type="long" insert="false"/>
文章来源: Hibernate Issue : Foreign key must have same number of columns as referenced primary key