2016-08-10 8 views
0

N1QL 쿼리 구문을 사용하여 값 이외의 값을 주입하려고하지만 작동하지 않습니다.매개 변수 이외의 값을 입력하십시오.

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

내가 성공적으로 관리하는 자바에 값을 을 주입하고 올바른 결과를 얻을 :

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

그러나 내가 주입 관리 할 수 ​​없습니다 여기

순수 N1QL 쿼리입니다 다른 항목 (예 : 매개 변수). 이 작동하지 않습니다
// 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 쿼리에 값은 보통 ('') 따옴표로 포장하고 필요는 없습니다 것을 고려하면, 내가 두려워 스프링 데이터 카우치베이스 주식회사 해요 항상 작은 따옴표 나 큰 따옴표를 가진 요소를 주입 랩핑 (따라서 내 쿼리는 카우치베이스 주식회사가 어떤 결과를 반환하지 않는 이유를 설명

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

로 변환된다).

내가 뭔가를 놓쳤습니까? 그렇지 않으면 spring-data-couchbase에서 quote injection을 우회 할 방법이 있습니까?

은 내가 단순히 com.couchbase.client.java.Bucket를 사용하고에 query를 호출 할 수 있습니다 알고 있지만, 이것은 항상 POJO를 조작하고, JSON 조작을 숨길 수있는, 나를 위해 스프링 데이터 카우치베이스 주식회사의 요점을 잃는다.

감사합니다.

답변

0

$1은 실제로 매개 변수가있는 명령문에 N1QL 구문을 사용하고 있습니다. 광범위하게 테스트하지는 않았지만 여기서 SpEL을 사용할 수 있습니다. SpEL에서 메서드 매개 변수를 사용하는 방법은 #{[x]} 구문을 사용하는 것입니다. 여기서 x은 사용할 매개 변수의 0 기반 인덱스입니다.

조심하지만 두 가지 방법을 혼합 : 즉시 $x는 성명에서 감지되는, 봄 데이터 카우치베이스 주식회사는 $의 X 자리를 채우려면 배열로 모든 메소드 인수를 사용합니다. 첫 번째 인수는 $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

궁금 해서요,이'# {[]}'구문을 어디에서 찾았습니까? 스프링 데이터 - couchbase 나 SpEL 문서 등 어디에서나 볼 수있는 기능/구문은 어디에도 없습니다. – jdebon

+1

은 스프링 데이터 JPA 문서 IIRC에서이를 발견했으며 SpEL 메서드 매개 변수 지원을 검색했습니다. 방금 Spring Data Couchbase 문서에 [이 커밋] (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'의 메소드를 사용할 수도 있습니다.이 메소드는 프레임 워크가 Couchbase SpEL 요소에 해당하는 DSL의 일부를 구성하는 데 사용됩니다. –

관련 문제