這是一個困惱了我一天的問題,這方面的問題網上的資料也是寥寥無幾,特此記錄。
如果要在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 }