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