Есть ли способ выполнить jpa-запрос spring data, чтобы узнать, содержит ли строка какую-либо другую строку в списке?

#java #spring-boot #spring-data-jpa #spring-data

Вопрос:

Поэтому я занимаюсь проектом, в котором у нас есть механика «тем», на самом деле очень похожая на механику переполнения стека. Поэтому я сохраняю каждую сущность (кулинарный рецепт) в переменной темы, которая содержит строку, разделенную запятыми. Теперь моя большая проблема здесь в том, что мне нужно найти темы, как и в нескольких темах. Я пробовал использовать @Query

 @Query("select new com.fullstack.dtos.projections.LocalizedRecipe(t.id, t.created, t.createdBy, t.lastModified, t.lastModifiedBy, t.version, l.title, l.description) from tutorial t inner join t.localizations l where l.id.locale = :lang and t.topics in :topics")
Page<LocalizedRecipe> findAllByTopics(String lang, Set<String> topics, Pageable page);
 

Я даже изменил свою модель так, чтобы темы представляли собой @elementколлекцию строк, пытающихся использовать один и тот же запрос, но всегда возникают ошибки типа. Большую часть времени он бросает:

 java.lang.IllegalArgumentException: Parameter value [Java] did not match expected type [java.util.Set (n/a)]
 

Мой вопрос здесь в том, как мне сделать так, чтобы это работало. Изменение моей модели не проблема, я просто не могу найти хороший способ сделать это.

Текущая модель:

 public class RecipeDAO {

@Id
    @GeneratedValue(generator = "uuid2", strategy = GenerationType.AUTO)
    @Column(columnDefinition = "BINARY(16)", unique = true)
    @GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
    private UUID id;

    @CreatedDate
    private LocalDateTime created;

    @CreatedBy
    private String createdBy;

    @LastModifiedDate
    private LocalDateTime lastModified;

    @LastModifiedBy
    private String lastModifiedBy;

    @Version
    private Integer version;

    private Boolean visible;

    private String topics;

    @MapKey(name = "id.locale")
    @OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, orphanRemoval = true)
    private Map<String, Localization> localizations;
}
 

Моя конечная цель здесь-проверить, есть ли, скажем, 3 рецепта с темами «завтрак, обед, ужин». Я хочу иметь возможность находить темы с помощью [«обед», «ужин»], и он возвращает их, возвращает все, у кого есть ужин или обед в строке тем
В основном сопоставитель подстрок. Или альтернативой для достижения этого, как я уже сказал, изменение модели не является проблемой

РЕДАКТИРОВАТЬ: Я также попытался перейти в список и стать @ElementCollection, но появилась ошибка. Я не знаю, смогу ли я увидеть, пересекаются ли два списка.

Комментарии:

1. Во-первых, ваша текущая модель не ясна из вопроса. Пожалуйста, поделитесь этим.

2. Также, пожалуйста, поделитесь методом репозитория и тем, какой параметр вы передаете для фильтрации ? Это строка или список?

3. Я отредактировал, чтобы включить текущую модель.

4. Его набор, при необходимости может быть списком или даже массивом java/varargs. Моя проблема в том, как выполнить запрос. Я хочу посмотреть, есть ли в параметре объекта «темы» какие-либо строки в наборе.

5. Вы можете проверить thorben-janssen.com/hibernate-tips-query-elementcollection а также, как предлагали другие, использование имен методов также должно работать

Ответ №1:

Вы должны быть в состоянии сделать это с In помощью ключевого слова следующим образом:

 findByTopicsIn(Collection<String> topics)
 

Ответ №2:

  1. В репозитории вы можете использовать метод производного запроса, где каждый параметр ссылается на свойства соответствующей сущности, например

    findByTopicsОрТопики(строка темы 1, строка темы 2);

соответствующий sql-запрос —

 select * from RecipeDAO where topics="topic1" OR topics="topic2";
 
  1. Если количество тем больше, то использование коллекции тем в качестве параметра в методе является лучшим выбором, чем передача каждой темы в качестве отдельного параметра.

Предоставление коллекции тем, запрещенных к использованию в

 List<RecipeDAO> findByTopicsIn(Collection<String> topics);
 

Соответствующий sql-запрос —

 select * from RecipeDAO where topics in('topics1','topics2',...,'topicsn');
 

Комментарии:

1. Я в курсе, но я не знаю, сколько будет тем. Может быть 1 может быть 2 может быть 10

2. Затем вы можете использовать производный метод запроса, предоставив набор тем для использования в List<RecipeDAO> findByTopicsIn(Collection<String> topics);

3. Сработает ли это в моем примере? Мне нужно было бы изменить темы на строку @ElementCollection правильно?