Запрос сущности по значениям в ElementCollections с использованием Spring Data JpaRepositories - PullRequest
0 голосов
/ 15 февраля 2019

Можно ли запрашивать объекты в JpaRepository на основании значений, хранящихся в прикрепленном @ElementCollection, с использованием методов запроса?

Настройка

My Spring Boot 2 /Приложение Spring 5 имеет сущность (Artwork), к которой могут быть прикреплены произвольные метаданные.Метаданные реализованы с помощью простой карты значений ключей с использованием @ElementCollection и @CollectionTable, поскольку метаданные представляют собой просто пары ключ / значение в виде текста и не существуют вне области его сущности.

Сущность выглядит следующим образом:

@Entity
@Table(name = "artwork")
public class Artwork implements Serializable {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    private Long id;

    // more propperties 

    @ElementCollection
    @MapKeyColumn(name = "name")
    @Column(name = "value")
    @CollectionTable(name = "artwork_metadata", joinColumns = @JoinColumn(name = "artwork_id"))
    private Map<String, String> metadata = new HashMap<>();

    // more code
}

Задача

У меня есть два варианта использования, когда мне нужно запросить сущность на основе информациихранится в карте метаданных.

  • Один вариант использования - поиск всех Artwork s с лицензиями (имеющих metadata.name = license, независимо от того, что находится в столбце значений)
  • Другой - поиск всех объектов одногоопределенный художник (имеющий точную пару ключ / значение metadata.name = artist и metadata.value = someName)

Я попытался использовать нотацию подчеркивания для описания пути свойства вручную;но мой тип данных - это карта, а не объект с полями name / value.

public interface ArtworkRepository extends JpaRepository<Artwork, Long> {
    List<Artwork> findAllByReleaseDateAfter(Instant after);

    // Not working
    List<Artwork> findAllByMetadata_NameAndMetadata_value 

Запрос в общем случае представляется возможным.Но большинство ответов, которые я нашел в StackOverflow, касаются поиска в списках , а не в картах.

Итак, мой вопрос

Как запросить объекты в JpaRepository на основе значений, хранящихся в прикрепленном @ElementCollection, с использованием методов запроса?Или мне нужно преобразовать это отношение на уровне объекта, используя отображение JPA «один ко многим».

Обновление

  • Поскольку у нас есть несколько десятков тысяч записей в таблице исполнителей, я хочу фильтровать на уровне базы данных, а не в приложении.
  • Запросы по метаданным станут обычным явлением, поэтому введение вспомогательных флагов, таких как hasLicense или перемещение исполнителя на основной объект, не вариант.

Спасибо.

1 Ответ

0 голосов
/ 19 февраля 2019

JPA 2.0 позволяет использовать KEY() и VALUE() для ссылки на ключ и значение на основе карты @ElementCollection в JPQL.

Обычно их можно использовать для решения вашей проблемы.Однако, как упомянуто в этом , Hibernate кажется странным поведением для VALUES() ...... К счастью, он имеет обходной путь .

В любом случае, ваша проблема может быть решена с помощью следующего @Query ( Предположим, вы используете Hibernate. Если вы используете других провайдеров, вы можете попробовать VALUES()) .:

public interface ArtworkRepository extends JpaRepository<Artwork, Long> {

    @Query(value = "select a from Artwork a join a.metadata meta where (KEY(meta) = :name)")
    public List<Artwork> findArtworkByMetadata(@Param("name") String name);

    @Query(value = "select a from Artwork a join a.metadata meta where (KEY(meta) = :name and meta = :value)")
    public List<Artwork> findArtworkByMetadata(@Param("name") String name, @Param("value") String value);

}

Чтобы найти все работы с лицензиями:

artworkRepository.findArtworkByMetadata("license");

Чтобы найти все работы определенного художника:

artworkRepository.findArtworkByMetadata("artist" , "someName");
...