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?