2016-08-10 7 views
0

Я пытаюсь внедрить что-либо другое, кроме значений, используя синтаксис запроса N1QL @Query, но не могу заставить его работать.Ввести ничего, кроме значения параметра

Вот чистый N1QL запрос:

SELECT * from `my-bucket` WHERE _class = 'my.package.MyModel' AND myParam = 'myValue' 

Я успешно удалось внедрить значение в Java и получить правильные результаты:

// In my repository 
@Query("#{#n1ql.selectEntity} WHERE myParam = $1 AND #{#n1ql.filter}") 
Collection<MyModel> myCustomSearch(String value); 
// In my business code 
myRepository.myCustomSearch("myValue"); 

Однако я не могу управлять, чтобы ввести что-нибудь еще (как параметр). Это не работает:

// In my repository 
@Query("#{#n1ql.selectEntity} WHERE $1 = 'myValue' AND #{#n1ql.filter}") 
Collection<MyModel> myCustomSearch(String param); 
// In my business code 
myRepository.myCustomSearch("myParam"); 

Учитывая, что в чистом N1QL запросе значение обычно заворачивают в одинарные кавычки («»), и это не нужно при закачке, я боюсь пружинными данных couchbase всегда оборачивает вводят элементы с одинарными или двойными кавычками (таким образом мой запрос преобразуется в

SELECT * from `my-bucket` WHERE _class = 'my.package.MyModel' AND 'myParam' = 'myValue' 

, который объясняет, почему Couchbase не возвращает никакого результата).

Я что-то пропустил? В противном случае, есть ли способ обойти цитату инъекции из spring-data-couchbase?

Я знаю, я мог бы просто использовать com.couchbase.client.java.Bucket и вызвать query на него, но это теряет весь смысл весенне-данных-couchbase для меня, который всегда манипулировать POJO, и скрыть манипуляции JSON.

Я ценю любую помощь!

ответ

0

$1 фактически использует синтаксис N1QL для параметризованных операторов. Я не тестировал его, но вы можете использовать SpEL здесь. Способ использования параметра метода в SpEL заключается в использовании синтаксиса #{[x]}, где x является индексом используемого параметра на основе 0.

осторожность при смешивании двух подходов, хотя: как только $x обнаруживается в заявлении, Spring Data Couchbase будет использовать все аргументы метода, так как массив для заполнения $ х заполнителей. Итак, первый аргумент будет отображаться в $1, второй - $2 и т. Д.

Так использовать как синтаксис (один динамически выбрать имя поля, а другой, чтобы N1QL вводить искомую величину), вы должны были бы написать что-то вроде:

@Query("#{#n1ql.selectEntity} WHERE #{[0]} = $2 AND #{#n1ql.filter}") 
public List<Entity> findAllBySomeCriteria(String fieldName, String value); 

Обратите внимание, как #{[0]} и $1 будет оба указывают на параметр fieldName, поэтому используемым заполнителем N1QL является $2, что указывает на value.

+0

Мне любопытно, где вы нашли этот синтаксис '# {[}}'? Я не видел его нигде в документах типа Spring-data-couchbase или SpEL, таких как функция/синтаксис. – jdebon

+1

нашел это в документе Spring Data JPA документации IIRC, в то время как поисковая система для поддержки параметров метода SpEL. Я просто добавил синтаксис и пример к документации Spring Data Couchbase в [this commit] (https://github.com/spring-projects/spring-data-couchbase/commit/415d8a2d2386f4387df95f54ff4a92467d57f7db) –

+0

Спасибо за обновление документации, высоко оценили :) – jdebon

0

Редактировать: См. Ответ @ simon-baslé, даже более короткий и элегантный, чем мой.


Я думаю, что я нашел самое лучшее решение для моих потребностей, в виде implementing a custom method in my repository.

public interface MyRepositoryCustom { 
    Collection<MyModel> customN1qlQuery(String query); 
} 

public interface MyRepository extends CrudRepository<MyModel, String>, MyRepositoryCustom { } 

public class MyRepositoryImpl implements MyRepositoryCustom { 

    @Autowired 
    RepositoryOperationsMapping templateProvider; 

    @Override 
    public Collection<MyModel> customN1qlQuery(String query) { 
    CouchbaseOperations template = templateProvider.resolve(MyRepository.class, MyModel.class); 
    return template.findByN1QL(N1qlQuery.simple(query), MyModel.class); 
    } 
} 

// In my business code 
Collection<MyModel> result = myRepository.customN1qlQuery("select META().id AS _ID, META().cas AS _CAS, * from `" + bucket.name() + "` where _class = '" 
      + MyModel.class.getCanonicalName() + "' and " + myCustomParam + " = '" + myCustomValue + "'"); 

Я продолжаю манипулировать POJO, но у меня есть полный контроль над запросом запроса N1QL. Единственным (второстепенным) недостатком является то, что я больше не могу вводить Spring SpEL syntax (например, #{#n1ql.selectEntity} для извлечения полного объекта или #{#n1ql.filter} для фильтрации имени класса сущности). Я нашел буквальный эквивалент (как показано в моем примере выше), поэтому я могу жить с этим.

+0

Вы также можете использовать методы в 'N1qlUtils', которые используются каркасом для создания частей DSL, соответствующих элементам Couchbase SpEL. –