涉及 M2M 关系的 Ebean AND 查询
Ebean AND query involving M2M relationship
我对使用 PlayFramework 2.2.3 的多对多关系的 AND 查询有疑问。我有 class 具有用户参与的线程列表的用户和 class 具有特定线程中涉及的用户列表的 MessageThread。
我的用户class:
@Entity
@Table(name="User")
public class User extends Model {
@Id
public String email;
.
.
.
@ManyToMany(cascade = CascadeType.ALL)
public List<MessageThread> threads = new ArrayList<MessageThread>();
和class MessageThread:
@Entity
public class MessageThread extends Model {
@Id
public Long id;
@ManyToMany(mappedBy="threads")
public List<User> users = new ArrayList<User>();
@OneToMany
public List<Message> messages = new ArrayList<Message>();
@Formats.DateTime(pattern="dd/MM/yyyy")
public Date date = new Date();
public MessageThread(User u1, User u2) {
this.users.add(u1);
this.users.add(u2);
}
public static MessageThread create(User u1, User u2) {
MessageThread mt = new MessageThread(u1, u2);
mt.save();
mt.saveManyToManyAssociations("users");
mt.update();
u1.threads.add(mt);
u1.update();
u2.threads.add(mt);
u2.update();
return mt;
}
public static Model.Finder<String, MessageThread> find = new Model.Finder<String, MessageThread>(
String.class, MessageThread.class);
public static List<MessageThread> findInvolving(String user1, String user2) {
return find.where().and(com.avaje.ebean.Expr.eq("users.email", user1),com.avaje.ebean.Expr.eq("users.email", user2))
.findList();
}
public boolean addMessage(Message m) {
this.messages.add(m);
return true;
}
}
我的数据库查询不正确吗?
public static List<MessageThread> findInvolving(String user1, String user2) {
return find.where().and(com.avaje.ebean.Expr.eq("users.email", user1),com.avaje.ebean.Expr.eq("users.email", user2))
.findList();
}
谢谢
编辑:我做了一些更多的测试,看起来我对数据库的查询是错误的,因为当我只做 where().eq("users.email", user1)
或 where().eq("users.email", user2)
它总是 returns 我相同的列表(因为我现在只有一个实体)但是当使用 AND 查询时它总是返回空列表
编辑:
这是一种基于建议的原始 SQL 查询为我工作的班轮。基本上在 Ebean 中也有 in() method/call (我不知道我应该使用 in 而不是 and)
find.where().in("users", new Object[]{user1, user2}).findUnique();
您可以使用接受的答案中提出的原始 SQL 查询或 Ebean 中的 in() 方法。
我通过创建自定义 SQL 查询找到了解决方案(类似的方法可能也适用于您的情况):
SELECT * FROM gom_conversation c INNER JOIN gom_user_gom_conversation u ON c.id = u.gom_conversation_id WHERE u.gom_user_id IN ('516645a0-7fc4-494f-9c96-8d83076ba17b', '6b37b10b-fcd1-48da-b635-b973105fa3b1') HAVING COUNT(DISTINCT u.gom_user_id) = 2;
这基本上将结果限制为包含两个匹配项的结果。
以及生成的 ebean 查询:
String sql = "SELECT id FROM gom_conversation c INNER JOIN gom_user_gom_conversation u " +
"ON c.id = u.gom_conversation_id " +
"WHERE " +
"u.gom_user_id IN (:user, :recipient) HAVING COUNT(DISTINCT u.gom_user_id) = 2;";
RawSql rawSql = RawSqlBuilder.parse(sql)
.tableAliasMapping("id", "id")
.create();
ConversationModel conversation = find.setRawSql(rawSql)
.setRawSql(rawSql)
.setParameter("user", user.id)
.setParameter("recipient", recipient.id)
.findUnique();
return conversation;
希望对你的情况有所帮助。
我对使用 PlayFramework 2.2.3 的多对多关系的 AND 查询有疑问。我有 class 具有用户参与的线程列表的用户和 class 具有特定线程中涉及的用户列表的 MessageThread。
我的用户class:
@Entity
@Table(name="User")
public class User extends Model {
@Id
public String email;
.
.
.
@ManyToMany(cascade = CascadeType.ALL)
public List<MessageThread> threads = new ArrayList<MessageThread>();
和class MessageThread:
@Entity
public class MessageThread extends Model {
@Id
public Long id;
@ManyToMany(mappedBy="threads")
public List<User> users = new ArrayList<User>();
@OneToMany
public List<Message> messages = new ArrayList<Message>();
@Formats.DateTime(pattern="dd/MM/yyyy")
public Date date = new Date();
public MessageThread(User u1, User u2) {
this.users.add(u1);
this.users.add(u2);
}
public static MessageThread create(User u1, User u2) {
MessageThread mt = new MessageThread(u1, u2);
mt.save();
mt.saveManyToManyAssociations("users");
mt.update();
u1.threads.add(mt);
u1.update();
u2.threads.add(mt);
u2.update();
return mt;
}
public static Model.Finder<String, MessageThread> find = new Model.Finder<String, MessageThread>(
String.class, MessageThread.class);
public static List<MessageThread> findInvolving(String user1, String user2) {
return find.where().and(com.avaje.ebean.Expr.eq("users.email", user1),com.avaje.ebean.Expr.eq("users.email", user2))
.findList();
}
public boolean addMessage(Message m) {
this.messages.add(m);
return true;
}
}
我的数据库查询不正确吗?
public static List<MessageThread> findInvolving(String user1, String user2) {
return find.where().and(com.avaje.ebean.Expr.eq("users.email", user1),com.avaje.ebean.Expr.eq("users.email", user2))
.findList();
}
谢谢
编辑:我做了一些更多的测试,看起来我对数据库的查询是错误的,因为当我只做 where().eq("users.email", user1)
或 where().eq("users.email", user2)
它总是 returns 我相同的列表(因为我现在只有一个实体)但是当使用 AND 查询时它总是返回空列表
编辑:
这是一种基于建议的原始 SQL 查询为我工作的班轮。基本上在 Ebean 中也有 in() method/call (我不知道我应该使用 in 而不是 and)
find.where().in("users", new Object[]{user1, user2}).findUnique();
您可以使用接受的答案中提出的原始 SQL 查询或 Ebean 中的 in() 方法。
我通过创建自定义 SQL 查询找到了解决方案(类似的方法可能也适用于您的情况):
SELECT * FROM gom_conversation c INNER JOIN gom_user_gom_conversation u ON c.id = u.gom_conversation_id WHERE u.gom_user_id IN ('516645a0-7fc4-494f-9c96-8d83076ba17b', '6b37b10b-fcd1-48da-b635-b973105fa3b1') HAVING COUNT(DISTINCT u.gom_user_id) = 2;
这基本上将结果限制为包含两个匹配项的结果。
以及生成的 ebean 查询:
String sql = "SELECT id FROM gom_conversation c INNER JOIN gom_user_gom_conversation u " +
"ON c.id = u.gom_conversation_id " +
"WHERE " +
"u.gom_user_id IN (:user, :recipient) HAVING COUNT(DISTINCT u.gom_user_id) = 2;";
RawSql rawSql = RawSqlBuilder.parse(sql)
.tableAliasMapping("id", "id")
.create();
ConversationModel conversation = find.setRawSql(rawSql)
.setRawSql(rawSql)
.setParameter("user", user.id)
.setParameter("recipient", recipient.id)
.findUnique();
return conversation;
希望对你的情况有所帮助。