2013-11-04 167 views
0

我想我们非主键作为外键在我的应用程序。这里是场景: 我有EMPLOYEE和EMPLOYEE_PROPERTIES表。员工和员工属性之间存在一对多的关系。这里是我的架构:休眠外键映射到唯一键


create table employee(
fname varchar2(100) not null, 
lname varchar2(100) not null, 
emp_id number not null 
); 
ALTER TABLE employee ADD constraint employee_pk PRIMARY KEY (fname, lname); 
alter table employee add constraint employee_uniue unique (emp_id); 

create table employee_property(
emp_prop_id not null, 
emp_id number not null, 
property_name varchar2(100) not null, 
property_value varchar2(100) not null 
); 
ALTER TABLE employee_property ADD constraint employee_property_pk PRIMARY KEY (emp_prop_id); 
ALTER TABLE employee_property ADD CONSTRAINT emp_prop_fk FOREIGN KEY (emp_id) REFERENCES employee(emp_id); 

这里是我的Hibernate映射个XML: -----------------员工------ ------------------

<hibernate-mapping> 
    <class name="com.persistence.vo.Employee" table="EMPLOYEE"> 
     <composite-id> 
      <key-property name="fName" column="FNAME"/> 
      <key-property name="lName" column="LNAME"/> 
     </composite-id> 
     <property name="empId" type="long" access="field" unique="true"> 
      <column name="EMP_ID" /> 
     </property> 
     <set name="employeeProperties" table="employee_properties" lazy="false" 
      fetch="select" cascade="save-update, delete-orphan"> 
      <key> 
       <column name="emp_id" not-null="true"/> 
      </key> 
      <one-to-many entity-name="com.persistence.vo.EmployeeProperty"/> 
     </set> 
    </class> 
</hibernate-mapping> 

-------------------员工属性 - --------------------

<hibernate-mapping> 
    <class name="com.persistence.vo.EmployeeProperty" table="EMPLOYEE_PROPERTY"> 
     <id name="empPropId" type="long"> 
      <column name="EMP_PROP_ID" /> 
      <generator class="assigned" /> 
     </id> 
    <many-to-one name="employee" class="com.persistence.vo.Employee" fetch="select"> 
     <column name="empId" not-null="true"/> 
    </many-to-one> 
     <property name="propertyName" type="java.lang.String"> 
      <column name="PROPERTY_NAME" /> 
     </property> 
     <property name="propertyValue" type="java.lang.String"> 
      <column name="PROPERTY_VALUE" /> 
     </property> 
    </class> 
</hibernate-mapping> 

----------- Employee.java -------------------------

public class Employee { 

    private long empId; 
    private String fName; 
    private String lName; 

    private Set<EmployeeProperty> employeeProperties; 
} 

------------ EmployeeProperty.java -------------------

public class EmployeeProperty { 

    private long empPropId; 
    private Employee employee; 
    private String propertyName; 
    private String propertyValue; 
} 

我不断收到当我尝试访问Employee时出现以下异常: 引起:org.hibernate.MappingException:外键(FKF28BCC4680C757 C:EMPLOYEE_PROPERTY [emp_id]))必须与引用的主键(EMPLOYEE [FNAME,LNAME])具有相同的列数。

是否可以引用非主键作为外键?

+0

是否有什么理由不让emp_id成为PK?使用fname和lname的组合键可能不是一个好主意 - 在这个世界上有很多约翰米勒尔。 – zencv

+0

是的,在这个特定的例子中,将empId作为主键是有意义的。但这只是我写下的一个例子。我正在致力于遗留系统,其中主键是具有差异5列的复合键。我打算用sigle id替换它。但是还有一些其他的外键引用这个组合键,我也必须删除它们。我只是想前进,我可以创建唯一的ID列,并将其用作我将添加的所有新表的外键。 –

回答

0

我对你的映射感到困惑。 Employee到EmployeeProperty是一对多的,但EmployeeProperty中的emp_id在映射中标记为此实体的ID字段(即PK,唯一列)?

使用不同的选项:

[1]添加另一个字段EmployeeProperty到例如充当ID emp_property_id

[2]制作EmployeeProperty的嵌入式(没有自己的持久性身份),而不是一个实体

鉴于EmployeeProperty依赖于员工(即EmployeeProperty不能将员工的独立存在),第二个选项可能更正确。

http://en.wikibooks.org/wiki/Java_Persistence/Embeddables

+0

在我的情况下,我可以为我的属性表添加emp_property_id。但是这些属性不是可嵌入的。可以通过Employee的多个属性,我不想在每个属性的Employee表中添加列。我只是想知道我是否可以使用唯一键作为外键。 –

+0

这并不意味着你不能使用Embeddable。您只需映射为ElementCollection(Hibernate特定API中的CollectionOfElements)即可。请参阅前面链接中的2.7:http://en.wikibooks.org/wiki/Java_Persistence/Embeddables#Collections –