Загруженный элемент с нетерпением и ленивостью всегда пуст в отношениях JPA «один ко многим» - PullRequest
0 голосов
/ 09 апреля 2010

У меня есть две сущности: пользователь и роль с отношением «один ко многим» от пользователя к роли. Вот как выглядят таблицы:

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 также распознал отношения достаточно, чтобы поставить данные на первое место.

Какие проблемы могут вызывать эти симптомы?

Ответы [ 2 ]

1 голос
/ 10 апреля 2010

Для меня существует некоторое несоответствие между вашей физической моделью и отображением ваших сущностей: физическая модель реализует отношение «многие ко многим» (с таблицей соединений), в то время как отображение объявляет «один ко многим». связь. IMO, физическая модель «правильная»: один пользователь может иметь много ролей, одна роль может быть связана со многими пользователями. Другими словами, отношение между Пользователем и Ролями много ко многим.

0 голосов
/ 10 апреля 2010

Хорошо, я обнаружил несколько различных симптомов, которые вызывают проблему:

  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>

Оказывается, что любое решение работает, но решение «многие ко многим» предполагает, что у меня есть поле в моем объекте роли, которое позволяет мне запрашивать (и/ или установить) пользователей.Это упростит управление ролями.

...