Охоплення колекцій сутностей, що містять інші захоплені колекції

Я застряг на відношенні M: N між об'єктом і рядками. Користувач може мати більше однієї ролі, і кожна роль може бути призначена більше ніж одному користувачеві. Роль - це лише рядок. Ролі містяться в таблиці з двома стовпчиками: roleId і roleName .

Я створив два об'єкти, але я абсолютно не можу це зробити. Першим об'єктом є користувач:

@Entity
@Table(name="appUsers")
public class UserEntity {
    @Id
    private String login;
    private String password;
    @OneToMany(fetch=FetchType.EAGER,mappedBy="user") //we always need to load user's roles
    private Collection roles;
    @Transient
    private Collection roleNames;

    public String getLogin() {
        return login;
    }

    public String getPassword() {
        return password;
    }

    @PostLoad
    void prepareRoleNames() {
        roleNames = new HashSet(roles.size());
        for (UsersToRoles mapping : roles)
            roleNames.add(mapping.getNameOfRole());
    }

    public Collection getRoles() {
        return roleNames;
    }
}

Другий - це сутність, пов'язана зі сполучною таблицею:

@Entity
@IdClass(UsersToRolesId.class)
public class UsersToRoles {
    @Id
    @SuppressWarnings("unused")
    @Column(name="login")
    private String login;
    @Id
    @SuppressWarnings("unused")
    @Column(name="roleId")
    private int roleId;
    @ElementCollection(fetch=FetchType.EAGER)
    @CollectionTable(name="userRoles", joinColumns={@JoinColumn(name="roleId")})
    private List roleName;
    @ManyToOne
    @JoinColumn(name="login")
    @SuppressWarnings("unused")
    private UserEntity user;

    public String getNameOfRole() {
        if (roleName.isEmpty())
            throw new CommonError("Role name for roleId=" + roleId, AppErrors.ACCESSOR_UNAVAILABLE);
        return roleName.get(0);
    }
}

class UsersToRolesId {
    private String login;
    private int roleId;

    /**
     * Implicit constructor is not public. We have to
     * declare public non-parametric constructor manually.
     */
    public UsersToRolesId() {
    }

    @Override
    public int hashCode() {
        return 17*login.hashCode() + 37*roleId;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof UsersToRolesId))
            return false;
        UsersToRolesId ref = (UsersToRolesId)obj;
        return (this.login.equals(ref.login) && this.roleId == ref.roleId);
    }
}

І проблема полягає в тому, що колекція roleName завжди нульова. Я не можу це зробити. Коли я помиляюся в назві таблиці в анотації @CollectionTable , вона все ще працює. JPA не отримує підколекції взагалі. Це робить вибір з таблиці користувача, об'єднаного з таблицею UsersToRoles , але прив'язка до таблиці userroles відсутня.

Чи можу я коли-небудь зробити це? Чи можу я з нетерпінням чекати колекцію сутностей, що містять інші захоплені колекції?

1

2 Відповіді

Ваше відображення повністю неправильне. UsersToRoles має стовпець roleId . Таким чином, це стосується єдиної ролі. Як може мати колекцію назв ролей? Стовпець входу вказується двічі у сутності. Крім того, це виглядає як простий приєднаний стіл для мене, без будь-якого іншого атрибута, аніж roleId та логіну, які є зовнішніми ключами для ідентифікаторів користувача та ролі, відповідно.

У вас має бути два об'єкти: User і Role з асоціацією ManyToMany , використовуючи таблицю UsersToRoles як приєднану таблицю. Це воно. Таблиця UsersToRoles не повинна відображатися як сутність: це чиста таблиця приєднання.

1
додано

Провайдерам JPA зазвичай є властивість конфігурації, яка відображає глибину завантаження за замовчуванням, тобто hibernate.max_fetch_depth для сплячого режиму. Перевірте, чи ви можете побачити більше, коли ви збільшите його.

Також подумайте про свій дизайн. Несподівано, витягування підколекцій колекції може бути гарною ідеєю лише у обмежених сценаріях (продуктивність). Коли ви коментуєте своє об'єднання таким чином, ви збираєтеся використати намір отримувати всі випадки використання. Можливо, вам буде краще з "леним" і отримувати його з охотою тільки явно, з запитом з пропозицією JOIN FETCH?

1
додано