Как сделать левое соединение по двум параметрам в Ebean?

У меня есть две таблицы: "users" и "mail_list" с соответствующими классами.
Эти таблицы связаны с помощью внешнего ключа user_id (в таблице mail_list), который ссылается на id (в таблице users). Пользователи могут иметь записи двух kinds в таблице mail_list - "общий" и/или "админ". Если у пользователя есть запись в таблице mail_list, это означает, что он не хочет получать письма соответствующего типа.
Я хочу найти всех пользователей, которые хотят получать письма общего вида. Я уверен, что правильный SQL-запрос выглядит так:

SELECT U.id, U.email, M.user_id, M.kind
FROM users U
LEFT JOIN mail_list M
ON (U.id = M.user_id AND M.kind = 'general')
WHERE M.user_id IS NULL

Но, к сожалению, я не очень хорошо разбираюсь в Ebean. Не могли бы вы помочь мне написать такой Ebean-запрос, если это возможно? Я бы хотел избежать использования Raw SQL.

Вот также код моих классов:

@Entity
@Table(name = "users")
public class User {
    @Id
    public Long id;

    public String email;

    @OneToMany(mappedBy = "user")
        public List<MailList> mailLists;
    }

    @Entity
    @Table(name = "mail_list")
    public class MailList {
        @Id
        public Long id;

    /**
     * Kind of mail list
     */
    public String kind;
    public static String GENERAL = "general";
    public static String ADMIN = "admin";

    @ManyToOne
    public User user;
}

Я использую PlayFramework 2.2.3.


person velika12    schedule 08.08.2014    source источник
comment
Я думаю, что у вас есть неправильный пункт в вашем SQL. Почему вы хотите использовать поле в таблице соединений и в том месте, где вы фильтруете нулевые идентификаторы? Этот запрос: ВЫБЕРИТЕ U.id, U.email, M.user_id, M.kind FROM пользователей U LEFT JOIN mail_list M ON (U.id = M.user_id AND M.kind = 'general'), ГДЕ M.user_id IS NULL . Часть where не имеет смысла.   -  person endrigoantonini    schedule 16.02.2015


Ответы (2)


Мое решение вашей проблемы:

List<MailList> mailList = MailList.find.where().like("kind", "general").findList();     
Set<User> userSet = new HashSet<User>();
for(MailList mail:mailList)
    userSet.add(mail.user);

Он находит списки рассылки, соответствующие критериям поиска. Затем он создает набор пользователей.

person rtruszk    schedule 05.01.2015

Я думаю, это то, что вы ищете:

    Finder<Long, User> finder = new Finder<Long, User>(Long.class, User.class);
    List<User> users = finder.fetch("mailLists").where().eq("mailLists.kind", "general").findList();

Этот фрагмент кода сгенерирует следующий запрос:

SELECT U.id, U.email, M.user_id, M.kind
FROM users U
LEFT JOIN mail_list M ON U.id = M.user_id
WHERE M.kind = 'general';

Я предлагаю вам использовать enum вместо статических строк. Это будет лучше ссылаться на ваш исходный код.

Уникальная часть, которую я не понял в вашем вопросе, - это та часть, в которой вы используете поле для присоединения к таблице, но в том месте, где вы фильтруете нулевые значения этого поля.

person endrigoantonini    schedule 16.02.2015