查找集合字段包含任何给定项的所有条目

时间:2017-01-28 13:41:39

标签: java spring spring-data-jpa h2

我有一个Spring Boot应用程序,它包含一个这样的实体(为了紧凑而剥离了一些字段):

@Entity
public class Message extends AbstractPersistable<Long> {
    @ManyToMany(targetEntity = Tag.class, fetch = FetchType.EAGER)
    private Set<Tag> tags;
    // getter and setter for tags here
}

Tag只是一个带名称字段的简单实体。

现在,我在代码中从用户那里获得了另一个Set<Tag>。我想查找具有此集合中任何标记的所有Message。例如,如果我们有以下消息:

ID    TAGS
1     1, 2, 3
2     2, 5, 7
3     2, 4, 7

然后,在给定[3, 4]集返回消息1和3的情况下,查询应该。

我尝试编写此存储库:

public interface MessageRepository extends JpaRepository<Message, Long> {
    List<Message> findByTags(Set<Tag> tag);
}

我已启用query logging并且我的代码生成了一个查询,我在这里清理了一下。在我尝试的情况下,查询没有产生任何结果,我不知道scalar = array比较正在做什么。

SELECT message.id AS id FROM message
LEFT OUTER JOIN message_tags ON message.id = message_tags.message_id
LEFT OUTER JOIN tag ON message_tags.tags_id = tag.id
WHERE tag.id = (1,2,3,4,5) -- this is the input set

正如@AliDehghani所建议的,我尝试将该方法编写为findByTagsIn(Set<Tag> tag)。这会将最后=替换为查询中的in

我得到了结果,但还有另一个问题:对于每个匹配的标记重复结果,可能会从查询中猜到。例如,使用上面的示例消息搜索[2, 7]将返回消息1,消息2返回两次,消息3返回两次。

据我所知,添加某种GROUP BY子句可能对此有所帮助。

predefined query method keywords似乎没有与此相关的任何功能,因此我认为我必须使用@Query或其他内容编写自己的功能。

我似乎无法找出一个可以工作的查询,而且我在H2中不是很有经验,所以我真的不想猜测一个人如何工作。

我不想编写一个方法来查找具有单个标记的所有消息,为每个标记调用它并组合结果,因为这将是丑陋的,并且给定大量标记作为输入,非常慢。我该如何编写查询方法?

1 个答案:

答案 0 :(得分:5)

  

列出findByTags(设置标签);

从查询日志中可以看出,此查询方法只会查找标记为给定tag参数中所有标记的邮件,这不是您想要的。

要查找使用其中任何一个标记标记的邮件,您可以使用以下查询方法:

List<Message> findByTagsIn(Set<Tag> tag);
  

我得到了结果,但还有另一个问题:结果是   可以从查询中猜测每个匹配标记的重复次数。

为了摆脱那些重复的消息,你只能获取不同的值:

List<Message> findDistinctByTagsIn(Set<Tag> tag);