Я создаю Java приложение с Hibernate.
Я изо всех сил пытаюсь получить то, что хочу, без тысячи кодов котельной плиты.
У меня есть система управления пользователями.
A user
может быть частью team
(отношения @ManyToMany).
A team
может быть частью debate
(отношения @ManyToMany).
A debate
может быть public
.
A user
может быть guest
из debate
(отношение @ManyToMany).
A debate
имеет user
, которому он принадлежит (отношение @ManyToOne).
Вот моя реализация
@Entity
@Table(name = "users")
public class User {
@ManyToMany(mappedBy = "users")
private Set<Team> teams = new HashSet<>();
@ManyToMany(mappedBy = "guests")
private Set<Debate> invitedDebates = new HashSet<>();
@OneToMany(mappedBy = "owner")
private Set<Debate> createdDebates = new HashSet<>();
[...]
}
@Entity
@Table(name = "teams")
public class Team {
@ManyToMany(mappedBy = "teams")
private Set<Debate> debates = new HashSet<>();
@JoinTable(name = "teams_users",
joinColumns = {
@JoinColumn(name = "team_id", referencedColumnName = "id")},
inverseJoinColumns = {
@JoinColumn(name = "user_id", referencedColumnName = "id")})
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
private Set<User> users = new HashSet<>();
[...]
}
@Entity
@Table(name = "debates")
public class Debate {
@Column(name = "open_public")
private boolean openPublic;
@JoinColumn(name = "owner_id", referencedColumnName = "id", updatable = false)
@ManyToOne(optional = false)
private User owner;
@JoinTable(name = "debates_teams",
joinColumns = {
@JoinColumn(name = "debate_id", referencedColumnName = "id")},
inverseJoinColumns = {
@JoinColumn(name = "team_id", referencedColumnName = "id")})
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
}, fetch = FetchType.EAGER)
private Set<Team> teams = new HashSet<>();
@JoinTable(name = "debates_guests",
joinColumns = {
@JoinColumn(name = "debate_id", referencedColumnName = "id")},
inverseJoinColumns = {
@JoinColumn(name = "user_id", referencedColumnName = "id")})
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
}, fetch = FetchType.EAGER)
private Set<User> guests = new HashSet<>();
[...]
}
То, что я хотел бы получить: с известным user
, выбирающим все debate
s, которые либо опубликованы c, либо созданный user
, либо в котором есть team
, к которому принадлежит user
.
Пока я делаю этот запрос
session.createQuery("SELECT d "
+ "FROM Debate d "
+ "LEFT JOIN d.teams t"
+ "LEFT JOIN User u "
+ " ON u = d.owner "
+ " OR u IN (d.guests) "
+ " OR u IN (t.users) "
+ "WHERE u = :user "
+ " OR d.options.openPublic = :isPublic", Debate.class)
.setParameter("user", myUser)
.setParameter("isPublic", true)
.getResultList();
Во-первых ... это некрасиво.
Во-вторых, мое приложение, если оно намного больше (debate
принадлежит document
, которое относится к category
, существует right
управление user
s, et c, et c ...), поэтому я должен повторно использовать этот образец кода в другой форме во многих разных местах.
Мне интересно, нельзя ли все это сделать с помощью Hibernates @ Filters.
Легко интегрировать для owner
и openPublic
, но я не могу установить фильтр типа user IN teams.users
Надеюсь, мои объяснения не слишком запутаны!