У меня есть сущности User, Organization и GrantedRole. Их отношение состоит в том, что GrantedRole определяет роль, которую Пользователь имеет в Организации. Все три объекта наследуют поле «id» (аннотированное с помощью @Id) из своего суперкласса. Организация не имеет ссылок на GrantedRole или User, эти отношения однонаправлены.JPA Присоединиться к нескольким столбцам
@Entity
@Table(name = "role_assignments", uniqueConstraints = @UniqueConstraint(columnNames = {
"user_id", "organization_id" }))
public class GrantedRole extends DomainEntity implements GrantedAuthority {
public static enum Role {
ROLE_MODM_USER, ROLE_MODM_ORGADMIN, ROLE_MODM_ADMIN
}
private User user;
private Role role;
private Organization organization;
public static enum Role {
ROLE_MODM_USER, ROLE_MODM_ORGADMIN, ROLE_MODM_ADMIN
}
@ManyToOne
@NotNull
public User getUser() {
return user;
}
@NotNull
@Enumerated(EnumType.STRING)
public Role getRole() {
return role;
}
@ManyToOne
public Organization getOrganization() {
return organization;
}
// Some setters
}
@Entity
@Table(name = "modmUsers")
public class User extends DomainEntity implements UserDetails {
// Some other fields
private Set<GrantedRole> roles = new HashSet<GrantedRole>();
private Set<Organization> organizations = new HashSet<Organization>();
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
public Set<GrantedRole> getRoles() {
return roles;
}
@ManyToMany(fetch = FetchType.EAGER)
public Set<Organization> getOrganizations() {
return organizations;
}
// Some setters
}
Теперь я хочу использовать JPA критерии, чтобы найти организации, в которых пользователь имеет роль ROLE_MODM_ORGADMIN. Но сгенерированный запрос объединяется в один столбец, что приводит к повторению строк из GrantedRole, поскольку User.id не уникален в GrantedRole и не является Organization.id. Комбинация обоих уникальна.
Мой код для нахождения организации:
public List<Organization> findOrganizationsByOrgAdminUser(String
CriteriaBuilder cb = entityManager.
CriteriaQuery<Organization> query = cb.createQuery(Organization.
Root<User> root = query.from(User.class);
SetJoin<User, Organization> joinOrg = root.joinSet("organizations");
SetJoin<User, GrantedRole> joinRoles = root.joinSet("roles");
Predicate p1 = cb.equal(root.get("id"), userId);
Predicate p2 = cb.equal(joinRoles.get("role"), Role.ROLE_MODM_ORGADMIN);
query.select(joinOrg);
query.where(cb.and(p1, p2));
return entityManager.createQuery(query).getResultList();
}
Сформированный запрос является:
SELECT
orgs.*
FROM
modmUsers users
INNER JOIN
modmUsers_organizations u_o
ON users.id=u_o.modmUsers_id
INNER JOIN
organizations orgs
ON u_o.organization_id=orgs.id
INNER JOIN
role_assignments roles
ON users.id=roles.user_id
WHERE
users.id=?
and roles.role=?
Запрос Я хочу это:
SELECT
orgs.*
FROM
modmUsers users
INNER JOIN
modmUsers_organizations u_o
ON users.id=u_o.modmUsers_id
INNER JOIN
organizations orgs
ON u_o.organization_id=orgs.id
INNER JOIN
role_assignments roles
ON users.id=roles.user_id
AND orgs.id=roles.organization_id //how to do this???
WHERE
users.id=?
and roles.role=?