如何确定一个列表是否包含另一个列表中的所有元素?

3

在我的Spring Boot项目中,我定义了一个聊天和用户实体,它们之间是多对多关系。

Chat.java

@ManyToMany
@JoinTable(name = "chat_user",
        joinColumns = @JoinColumn(name = "chat_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"))
private Set<User> users = new HashSet<User>();

public Set<User> getUsers() {
    return users;
}

public void setUsers(Set<User> users) {
    this.users = users;
}

User.java

@ManyToMany
@JsonBackReference
@JoinTable(name = "chat_user",
        joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "chat_id", referencedColumnName = "id"))
private Set<Chat> chats = new HashSet<Chat>();

public Set<Chat> getChats() {
    return chats;
}

public void setChats(Set<Chat> chats) {
    this.chats = chats;
}

如何在CrudRepository中编写一个方法,以便我获得包含用户列表中所有用户的聊天列表。
到目前为止,我已经编写了一个返回包含用户列表中任何用户的聊天列表的方法。
public interface ChatRepo extends CrudRepository<Chat, Long> {
List<Chat> findAllByUsers(User user);
List<Chat> findDistinctByUsersIn(Set<User> users);
}

这里有什么问题?获取所有聊天记录,遍历它们并检查它们的用户集合(不是列表)是否包含传递的用户集合。你可以使用containsAll()方法之一。优化的一种方式是在查询中执行此操作。可能有一些HQL函数可以实现这个(我记不清了),但是一个快速的查询得出了这个结果:https://dev59.com/mGnWa4cB1Zd3GeqPzVak - Thomas
我刚试过这种方法,但是当应用containsAll()方法时,它总是返回false作为响应。因此,我想检查是否有一种方法可以使用存储库方法获取该响应。 - Ante Ereš
我理解的是,您有一个用户列表,并且想要获取每个用户的所有聊天记录作为一个单独的列表?我理解得对吗? - Jayesh Choudhary
将包含接收到的用户列表中所有用户的所有聊天记录作为单个列表。 - Ante Ereš
1
你的 User 类是否正确实现了 equals/hashCode? 否则,containsAll 方法将无法正常工作。 - Malte Hartwig
谢谢Malte,你的答案对我很有帮助,我添加了@Override equals/hashCode方法,现在它可以正常工作了。 - Ante Ereš
3个回答

1
实现像Malte Hartwig建议的equals/hashCode就是解决方案。
@Override
public boolean equals(Object o) {

    if (o == this) return true;
    if (!(o instanceof User)) {
        return false;
    }
    User user = (User) o;
    return id == user.id &&
            Objects.equals(firstName, user.firstName) &&
            Objects.equals(lastName, user.lastName) &&
            Objects.equals(userName, user.userName) &&
            Objects.equals(password, user.password);
}

@Override
public int hashCode() {
    return Objects.hash(id, firstName, lastName, userName, password);
}

0

从我所见,这个问题没有直接的解决方案。你可以做的是
在你的ChatRepo中创建一个方法,像这样

public interface ChatRepository extends CrudRepository<Chat, Long> {

  @Query("select c from Chat c WHERE :user in elements(c.users)")
  List<Chat> getChatsWithUsers(@Param("user") User user);
}

这将为您获取此特定用户参与的所有聊天的结果。
然后,您可以对集合中的所有用户执行此操作,然后对结果进行交集运算。
为使其正常工作,您需要在聊天类中添加@ElementCollection

..........
@ElementCollection
  private Set<User> users = new HashSet<User>();

但我同意这并不是一个理想的解决方案,因为如果列表太大,那么就会导致多次数据库调用。


0
   @ManyToMany
 @JoinTable(name = "chat_user",
    joinColumns = @JoinColumn(name = "chat_id", referencedColumnName = "id"),
    inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = 
 "id"))
  private Set<User> users = new HashSet<User>();

  I think this is maybe wrong. Because one chat id cannot point out many user. 
  So you can use simple jointable to user entity

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接