2010-02-24 153 views
1

0..N我有一个表的用户映射两个表中的休眠


CREATE TABLE "USERS" (
    "ID" NUMBER NOT NULL , 
    "LOGINNAME" VARCHAR2 (150) NOT NULL) 

和我有一个第二表SpecialUsers。 SpecialUsers表中不会出现两次UserId,并且SpecialUsers表中仅包含用户表中的一小部分用户ID。


CREATE TABLE "SPECIALUSERS" (
    "USERID" NUMBER NOT NULL, 
CONSTRAINT "PK_SPECIALUSERS" PRIMARY KEY ("USERID")) 

ALTER TABLE "SPECIALUSERS" ADD CONSTRAINT "FK_SPECIALUSERS_USERID" FOREIGN KEY ("USERID") 
REFERENCES "USERS" ("ID") 
/

映射在Hibernate中用户表工作正常


<hibernate-mapping package="com.initech.domain"> 
    <class name="com.initech.User" table="USERS"> 

     <id name="id" column="ID" type="java.lang.Long"> 
      <meta attribute="use-in-tostring">true</meta> 
      <generator class="sequence"> 
       <param name="sequence">SEQ_USERS_ID</param> 
      </generator> 
     </id> 

     <property name="loginName" column="LOGINNAME" type="java.lang.String" not-null="true"> 
      <meta attribute="use-in-tostring">true</meta> 
     </property> 

    </class> 
</hibernate-mapping> 

但我创造了SpecialUsers表中的映射挣扎。 Internet上的所有示例(例如Hibernate文档中)都没有这种类型的自引用。我想这样的映射:


<hibernate-mapping package="com.initech.domain"> 
    <class name="com.initech.User" table="SPECIALUSERS">   

     <id name="id" column="USERID"> 
      <meta attribute="use-in-tostring">true</meta> 
      <generator class="foreign"> 
       <param name="property">user</param> 
      </generator> 
     </id> 

     <one-to-one name="user" class="User"/> 

    </class> 
</hibernate-mapping> 

,但得到的错误


Invocation of init method failed; nested exception is org.hibernate.DuplicateMappingException: 
Duplicate class/entity mapping com.initech.User

我应该如何映射SpecialUsers表?我在应用程序级别上需要的是SpecialUsers表中包含的用户对象列表。

+0

为什么不在USERS表中添加一个'特殊'字段? – 2010-02-24 15:23:50

+0

我认为,但考虑到很少有“特殊”用户(目前是一个)和很多用户,这看起来并不正确。长期来看,它还会使用户表不清楚是否每个小型资产(仅适用于一小部分用户)会直接添加到用户表中。还有一个原因是,如果“特殊”用户在未来应该拥有更多与他们“特殊性”相关的属性,则很容易扩展SpecialUsers表。 – simon 2010-02-24 15:32:26

+0

为什么你认为某处存在0..n关系?你的物理模型没有反映出来,它代表了纯粹的父子层次结构(即继承)。我错过了什么吗? – 2010-02-24 18:00:24

回答

2

我该如何映射SpecialUsers表?

根据您的USERSSPECIALUSERS表的结构,你有一个Table per subclass层次和这是完全可能的这种层次结构的映射与Hibernate

首先,确保SpecialUserUser在对象模型的水平(这是一种继承关系,而不是一个自我参照)继承

public class SpecialUser extends User { 
} 

然后,在User的映射声明<joined-subclass>元素:

<hibernate-mapping package="com.initech.domain"> 
    <class name="com.initech.User" table="USERS"> 

     <id name="id" column="ID" type="java.lang.Long"> 
      <meta attribute="use-in-tostring">true</meta> 
      <generator class="sequence"> 
       <param name="sequence">SEQ_USERS_ID</param> 
      </generator> 
     </id> 

     <property name="loginName" column="LOGINNAME" type="java.lang.String" not-null="true"> 
      <meta attribute="use-in-tostring">true</meta> 
     </property> 

     <joined-subclass name="com.initech.SpecialUser" table="SPECIALUSERS"> 
      <key column="USERID"/> 
     </joined-subclass> 

    </class> 
</hibernate-mapping> 

我需要在应用层是包含在SpecialUsers表用户对象的列表。

下面的HQL查询将返回所有的SpecialUser(这是User太):

from SpecialUser 

如果以后你需要列添加到SPECIALUSERS表,添加相应的属性添加到SpecialUser类将它们映射到<joined-subclass>元素内。有关详细信息,请参阅提供的链接(至文档)。

1

如果您确实需要使用第二个表格,则必须将其映射到新的类别。 Hibernate始终只能将一个表映射到一个类。

或者,在用户表中添加一列表示“此用户是特殊的”。如果这不是一个选项,请创建一个视图,将两个表连接起来,从而模拟此列。然后,您可以按此列选择用户。

如果你走两个班的方式,你必须加载一个特殊用户列表,并在你的应用程序中执行映射。

[编辑]也许你应该看看父母与孩子的关系。在你的情况下,用户是父母,其角色是孩子。所以每个用户都有0..n个角色,这些角色被映射到不同的表中。您可以使用此HQL

from User u where :role in elements(u.roles) 

查找具有特定角色的所有用户。但大多数情况下,你会有一个特定的用户,只需要询问她是否有特定的角色。

+0

谢谢,关于角色的观点很有见地。 – simon 2010-02-24 16:49:51

+0

Aaroon,虽然问题的标题很混乱,但我不认为你的编辑反映了最初的意图(它与你的答案相符,但这不是OP要求的恕我直言)。而物理模型并不代表0..n的关系BTW,它是纯粹的继承关系。 – 2010-02-24 18:09:18