JPQL — Как я могу искать сущности по ключу и значению (Hibernate OGM (MongoDB) — Map‹String, String›)

Я использую Hibernate OGM для MongoDB и сопоставляю простой объект ShopItem с Map:

@NamedQueries({
        @NamedQuery(name = ShopItem.GET_BY_NAME,
                    query = "select items from ShopItem items where 
                    items.name=:name"),
        @NamedQuery(name = ShopItem.GET_BY_OPTION,
                query = "select items from ShopItem items 
                        join items.options map 
                where ( KEY(map) = :optionKey and map = :optionValue )")
})
@Entity
public class ShopItem {

    public static final String GET_BY_NAME = "ShopItem.getByName";
    public static final String GET_BY_OPTION = "ShopItem.getByOption";

    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String id;

    private String name;

    @ElementCollection(fetch = FetchType.EAGER)
    private Map<String, String> options = new HashMap<>();
    //...etc
}

Это совпало хорошо. И я попытался написать именованные запросы JPQL для моего ShopItemRepository. Я искал NamedQuery по полю «имя», и он отлично работает. Но мне нужно искать по обоим полям «ключ» и «значение», и я не могу написать для этого правильный JPQL. Например, у меня есть объект в БД:

{
   "_id":"df111b8a-b831-4200-95b3-f80576cd7273",
   "name":"Example",
   "description":"My description",
   "options":
        {
            "weight":"60 kg",
            "age":"22"
        }
}

И я хочу найти все объекты, где параметры имеют ключ «возраст» и имеют значение «22».

Я пытаюсь написать:

select items from ShopItem items join items.options map where ( KEY(map) = :optionKey and map = :optionValue )

or

select items from ShopItem items join items.options map where ( KEY(map) = :optionKey and :optionValue in (VALUE(map))

or

select items from ShopItem items where ( KEY(items.options) = :optionKey and items.options = :optionValue )

or

select items from ShopItem items where ( KEY(items.options) = :optionKey and :optionValue in (VALUE(items.options))

И есть эта ошибка

org/hibernate/hql/ast/origin/hql/resolve/GeneratedHQLResolver.g: node from line 1:85 no viable alternative at input '('

can't look backwards more than one token in this stream

Мой код в репо:

List<ShopItem> result = entityManager.createNamedQuery(ShopItem.GET_BY_OPTION, ShopItem.class)
                .setParameter("optionKey", key)
                .setParameter("optionValue", value)
                .getResultList();

Можете ли вы помочь мне написать правильный запрос JPQL? А если это невозможно, то подскажите, как это сделать другим способом.

Я не могу использовать Spring Data JPA.


person Ryazan    schedule 12.09.2019    source источник


Ответы (1)


Прямо сейчас единственный способ запросить этот случай — использовать собственный запрос:

    List<ShopItem> results = session
            .createNativeQuery( "{ 'options.Weight': '60 Kg' }", ShopItem.class )
            .getResultList();

Вы по-прежнему можете объявлять запросы, используя @NamedNativeQuery (вместо @NamedQuery), но параметры не поддерживаются для MongoDB.

person Davide    schedule 16.09.2019