首页 文章

注入除param值之外的任何内容

提问于
浏览
0

我正在尝试使用 @Query N1QL查询语法注入除值之外的任何内容但无法使其工作 .

这是纯N1QL查询:

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

我成功地设法在Java中注入 a value 并获得正确的结果:

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

但是我无法注入 anything else (like a param) . 这不起作用:

// 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查询中,该值通常用单引号('')包装,并且在注入它时没有必要,我担心spring-data-couchbase总是用单引号或双引号包装注入的元素(因此我的查询变成了

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

这解释了为什么Couchbase不会返回任何结果) .

我错过了什么?否则,有没有办法绕过spring-data-couchbase的引用注入?

我知道我可以简单地使用 com.couchbase.client.java.Bucket 并在其上调用 query ,但这对我来说总是失去了spring-data-couchbase的全部意义,即总是操纵POJO并隐藏JSON操作 .

我感谢任何帮助!

2 回答

  • 0

    $1 实际上只是对参数化语句使用N1QL语法 . 我没有对它进行过广泛的测试,但你可以在这里使用SpEL . 在SpEL中使用方法参数的方法是使用 #{[x]} 语法,其中 x 是要使用的参数的从0开始的索引 .

    但是在混合使用这两种方法时要小心:只要在语句中检测到 $x ,Spring Data Couchbase就会使用 all 方法参数作为数组来填充$ 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

    编辑:见@ 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} 来过滤实体类名称) . 我找到了字面上的等价物(如上面的例子所示),所以我可以忍受 .

相关问题