2010-04-09 23 views
0

我有两个实体,用户和角色与用户之间的一对多关系,角色。这里的表是什么样子:Eager /懒加载成员总是空与JPA一对多的关系

mysql> select * from User; 
+----+-------+----------+ 
| id | name | password | 
+----+-------+----------+ 
| 1 | admin | admin | 
+----+-------+----------+ 
1 row in set (0.00 sec) 

mysql> select * from Role; 
+----+----------------------+---------------+----------------+ 
| id | description   | name   | summary  | 
+----+----------------------+---------------+----------------+ 
| 1 | administrator's role | administrator | Administration | 
| 2 | editor's role  | editor  | Editing  | 
+----+----------------------+---------------+----------------+ 
2 rows in set (0.00 sec) 

而这里所创建的连接表:

mysql> select * from User_Role; 
+---------+----------+ 
| User_id | roles_id | 
+---------+----------+ 
|  1 |  1 | 
|  1 |  2 | 
+---------+----------+ 
2 rows in set (0.00 sec) 

和这里的的orm.xml定义表和关系的子集:

<entity class="User" name="User"> 
    <table name="User" /> 
    <attributes> 
     <id name="id"> 
      <generated-value strategy="AUTO" /> 
     </id> 
     <basic name="name"> 
      <column name="name" length="100" unique="true" nullable="false"/> 
     </basic> 
     <basic name="password"> 
      <column length="255" nullable="false" /> 
     </basic> 
     <one-to-many 
      name="roles" 
      fetch="EAGER" 
      target-entity="Role" 
      /> 
    </attributes> 
</entity> 

<entity class="Role" name="Role"> 
    <table name="Role" /> 
    <attributes> 
     <id name="id"> 
      <generated-value strategy="AUTO"/> 
     </id> 
     <basic name="name"> 
      <column name="name" length="40" unique="true" nullable="false"/> 
     </basic> 
     <basic name="summary"> 
      <column name="summary" length="100" nullable="false"/> 
     </basic> 
     <basic name="description"> 
      <column name="description" length="255"/> 
     </basic> 
    </attributes> 
</entity> 

然而,尽管如此,当我检索管理员用户时,我收回了一个空的集合。我使用Hibernate作为我的JPA提供者,它显示了以下调试SQL:

select 
    user0_.id as id8_, 
    user0_.name as name8_, 
    user0_.password as password8_ 
from 
    User user0_ 
where 
    user0_.name=? limit ? 

当一个一对多的映射延迟加载,这是一个的做出的唯一查询。这正确地检索一个管理员用户。我改变了这种关系用预先加载,然后下面的查询,除了上述提出:

select 
    roles0_.User_id as User1_1_, 
    roles0_.roles_id as roles2_1_, 
    role1_.id as id9_0_, 
    role1_.description as descript2_9_0_, 
    role1_.name as name9_0_, 
    role1_.summary as summary9_0_ 
from 
    User_Role roles0_ 
left outer join 
    Role role1_ 
     on roles0_.roles_id=role1_.id 
where 
    roles0_.User_id=? 

这将导致以下结果:

+----------+-----------+--------+----------------------+---------------+----------------+ 
| User1_1_ | roles2_1_ | id9_0_ | descript2_9_0_  | name9_0_  | summary9_0_ | 
+----------+-----------+--------+----------------------+---------------+----------------+ 
|  1 |   1 |  1 | administrator's role | administrator | Administration | 
|  1 |   2 |  2 | editor's role  | editor  | Editing  | 
+----------+-----------+--------+----------------------+---------------+----------------+ 
2 rows in set (0.00 sec) 

休眠显然知道有关的角色,但getRoles()仍然返回一个空集合。 Hibernate也充分认识到这种关系,足以将数据放在首位。

什么问题会导致这些症状?

回答

1

对我而言,物理模型和实体映射之间存在某种不匹配:物理模型实现了多对多关系(使用连接表),而映射声明了一对一的关系,很多关系。国际海事组织,物理模型是“正确的”:一个用户可以有许多角色,一个角色可以关联到许多用户。换句话说,用户和角色之间的关系是多对多的。

+0

关于多对多关系的好处。它并没有跨越我的想法,因为我还没有从另一个方向获取数据,但这是事实。 – 2010-04-09 23:59:07

0

好吧,我发现了几个不同的症状,导致问题:

  1. 用户错误。在这种情况下,我出错了,上面所有的东西都正常工作。我做了一个愚蠢的,(好吧...真的愚蠢)的错误。
  2. 模式变化。在一对多和多对多关系之间切换时,架构已更新,但我的数据未重新填充。由于数据未重新填充,连接表中的第三列为空,并且未使用,导致返回零记录。

多对多映射也适用。下面是它结束了看起来像:

<entity class="User" name="User"> 
    <table name="User" /> 
    <attributes> 
     <id name="id"> 
      <generated-value strategy="AUTO" /> 
     </id> 
     <basic name="name"> 
      <column name="name" length="100" unique="true" nullable="false"/> 
     </basic> 
     <basic name="password"> 
      <column length="255" nullable="false" /> 
     </basic> 
     <many-to-many 
      name="roles" 
      fetch="EAGER" 
      target-entity="Role" 
      /> 
    </attributes> 
</entity> 

<entity class="Role" name="Role"> 
    <table name="Role" /> 
    <attributes> 
     <id name="id"> 
      <generated-value strategy="AUTO"/> 
     </id> 
     <basic name="name"> 
      <column name="name" length="40" unique="true" nullable="false"/> 
     </basic> 
     <basic name="summary"> 
      <column name="summary" length="100" nullable="false"/> 
     </basic> 
     <basic name="description"> 
      <column name="description" length="255"/> 
     </basic> 
     <many-to-many 
      name="users" 
      mapped-by="roles" 
      /> 
    </attributes> 
</entity> 

事实证明,无论是解决方案的工作,但许多一对多解决方案假设我有我的角色对象中的一个字段,让我查询(和/或设置)用户。这将使角色管理更容易。