繁体   English   中英

渴望/延迟加载的成员总是空的,并且具有JPA一对多关系

[英]Eager/Lazy loaded member always empty with JPA one-to-many relationship

我有两个实体,一个用户和一个角色,用户与角色之间存在一对多的关系。 表格如下所示:

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)

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

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

对我而言,您的物理模型与实体的映射之间存在某种不匹配:物理模型实现了多对多关系(带有连接表),而映射则声明了一对多关系。 IMO,物理模型是“正确的”:一个用户可以具有多个角色,一个角色可以与多个用户相关联。 换句话说,用户和角色之间的关系是多对多的。

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

  1. 用户错误 在这种情况下,我出错了,上面的一切都正常运行。 我犯了一个愚蠢的(好吧,真的很愚蠢)的错误。
  2. 模式更改 在一对多和多对多关系之间进行切换时,已更新了架构,但是没有重新填充我的数据。 由于未重新填充数据,因此联接表中的第三列为NULL,并且未使用,导致返回零记录。

多对多映射也可以。 最终结果如下所示:

<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>

事实证明,这两种解决方案都可以,但是多对多解决方案假定我的角色对象中有一个字段,该字段允许我查询(和/或设置)用户。 这将使角色管理更加容易。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM