Krijg gretig een verzameling entiteiten met andere gretig verzamelde collecties

Ik ben vastgelopen op de M: N-relatie tussen entiteit en tekenreeksen. Een gebruiker kan meer dan één rol hebben en elke rol kan aan meer dan één gebruiker worden toegewezen. De rol is slechts een tekenreeks. Rollen zijn opgenomen in de tabel met twee kolommen: roleId en roleName .

Ik heb twee entiteiten gemaakt, maar ik kan absoluut niet werken. Eerste entiteit is de gebruiker:

@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;
    }
}

De tweede is entiteit die is gekoppeld aan de verbindingstabel:

@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);
    }
}

En het probleem is dat de collectie roleName altijd null is. Ik kan het niet laten werken. Wanneer ik een fout maak in de tabelnaam in de annotatie @CollectionTable , werkt deze nog steeds. De PPV haalt de deelcollectie helemaal niet. Het maakt het selecteren van de tabel van de gebruiker samengevoegd met de tabel UsersToRoles , maar de join to table userRoles ontbreekt.

Kan ik dat ooit doen? Kan ik gretig verzameling entiteiten krijgen met een andere gretig opgehaalde collecties?

1

2 antwoord

Je mapping is helemaal verkeerd. UsersToRoles heeft een kolom roleId . Het verwijst dus naar een enkele rol. Hoe kan het een verzameling rolnamen hebben? De aanmeldingskolom wordt tweemaal in de entiteit afgebeeld. Bovendien lijkt dit op een eenvoudige join-tabel voor mij, zonder enige andere eigenschap dan de roleId en de login, die respectievelijk vreemde sleutels zijn voor de ID's van gebruiker en rol.

U moet twee entiteiten hebben: Gebruiker en Rol , met een ManyToMany koppeling met behulp van de tabel UsersToRoles als jointabel. Dat is het. De tabel UsersToRoles mag niet als een geheel worden toegewezen: het is een pure join-tabel.

1
toegevoegd

PPA-providers hebben meestal een configuratie-eigenschap die standaard gretige ophaaldiepte aangeeft, d.w.z. hibernate.max_fetch_depth voor Hibernate. Controleer of je meer kunt zien wanneer je het verhoogt.

Denk ook aan je ontwerp. Subverzamelingen van een verzameling gretig vinden is misschien slechts een goed idee in beperkte scenario's (qua prestaties). Wanneer u uw entiteit op deze manier annoteert, gebruikt u gretig ophalen in alle use-cases. Misschien bent u beter af met 'lui' en haalt u het gretig alleen expliciet op, met een vraag met een JOIN FETCH-clausule?

1
toegevoegd