Spring Data Jpa 构建动态查询表达式 使用Oracle特定数据库函数
这是一个困恼了我一天的问题,这方面的问题网上的资料也是寥寥无几,特此记录。
如果要在spring data jpa中使用oracle数据库的特定函数该怎么写呢?
本文以使用oracle相似度匹配函数UTL_MATCH.EDIT_DISTANCE_SIMILARITY()为例。该函数作用是匹配两个字符串的相似度,需要两个参数。返回值在0到100之间。
语法引自官网如下:
UTL_MATCH.EDIT_DISTANCE_SIMILARITY ( s1 IN VARCHAR2, s2 IN VARCHAR2)
RETURN PLS_INTEGER;
例如:SELECT UTL_MATCH.EDIT_DISTANCE_SIMILARITY('shackleford', 'shackelford') FROM DUAL;
--------------
returns 82
在以下的实例中,传递给该函数的两个参数,一个是动态的字段名,一个是个已知的字面量。由于参数类型都需要为Expression类型,动态字段参数还好构建,根据字面量构建Expression就有点不知所措了。
幸好在我的摸索下,发现了有LiteralExpression这个类型,顾名思义字面量表达式。可以作为第二个参数传递给函数使用。
由于是特定数据库的函数,故我们需要扩展该函数,CriteriaBuilder 接口提供了function()函数供我们使用。
实例代码:
1 List<AppMain> = appMainDao.findAll(new Specification<AppMain>() { 2 3 @Override 4 public Predicate toPredicate(Root<AppMain> root, 5 CriteriaQuery<?> query, CriteriaBuilder cb) { 6 List<Predicate> predicates = new ArrayList<Predicate>(); 7 predicates.addAll(DesCommonUtils.getPubConditon(root, query, cb)); 8 9 //本次进件之前 10 Path<Date> lastCreateDate = root.get("createdTime"); 11 predicates.add(cb.lessThanOrEqualTo(lastCreateDate, thisEntryCreateTime)); 12 13 //户籍地址相同 省市全匹配,详细地址模糊匹配 14 LiteralExpression<String> regitsterAdressExp = new LiteralExpression<String>(null, 15 StringUtils.trim2Empty(appCustomer.getRegisterAddress())); 16 17 Expression< Integer> similarityFunc = cb.function("UTL_MATCH.EDIT_DISTANCE_SIMILARITY", 18 Integer.class, root.get("appCustomer").get("registerAddress"),regitsterAdressExp); 19 20 predicates.add(cb.and( 21 cb.equal(root.get("appCustomer").get("registerProvince"), appCustomer.getRegisterProvince()), 22 cb.equal(root.get("appCustomer").get("registerCity"), appCustomer.getRegisterCity()), 23 cb.greaterThanOrEqualTo(similarityFunc, 80) 24 )); 25 26 return cb.and(predicates.toArray(new Predicate[predicates.size()])); 27 } 28 });
另外在hql中好像也不支持函数名称中带有.的sql。若需要在代码中使用,用@Query注解写原生sql,可加上nativeQuery属性。
例如:
1 public interface AppCustomerRepository extends PagingAndSortingRepository<AppCustomer, Long> , JpaSpecificationExecutor<AppCustomer>{ 2 3 @Query(value = "select UTL_MATCH.EDIT_DISTANCE_SIMILARITY('a','a') from DUAL ", nativeQuery = true) 4 Double getSimilarity(); 5 6 }