我尝试了各种选项,但对我不起作用。终于明白了,如果第二个参数是内置函数的数组,就是扩展变量,转换成myVarArgMethod。所以我做了什么,我编写了自己的自定义数据库函数,如下所示。
如果 searchKey 是单值我们可以使用 arrayContains,如果 searchKey 包含多个值,我们可以使用 java util 函数将列表转换为 postrgress 数组格式字符串,在 postgres 函数中,我们可以通过类型转换将其转换为数组。
用于将列表转换为 postgress 数组字符串以及反之亦然的 Java util 方法
public static String convertToPGArray(List<String> content){
StringBuilder str = new StringBuilder();
if(content != null){
str.append("{");
int counter = 0;
for(String text : content){
if(counter != 0){
str.append(",");
counter++;
}else{
counter++;
}
str.append("\"").append(text).append("\"");
}
str.append("}");
}else{
str.append("{}");
}
return str.toString();
}
public static List<String> convertToList(String content){
List<String> returnList = new ArrayList<>();
if(!(content == null || content.equals("{}") || content.trim().equals(""))){
String tempContent = content;
String[] tokens = tempContent.replace("{", "").replace("}", "").split(",");
returnList = Arrays.stream(tokens).collect(Collectors.toList());
}
return returnList;
}
arrayContains 和 arrayContainsAny 的自定义 postgres 函数
CREATE OR REPLACE FUNCTION arrayContains(arrayContent text[], searchKey text) RETURNS BOOLEAN as
'
DECLARE arrContent text[];
countVal integer :=0;
BEGIN
arrContent = $1::text[];
countVal = (SELECT count(array_position(arrContent, searchKey)));
IF countVal = 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;'
LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION arrayContainsAny(arrayContent text[], searchKeys text) RETURNS BOOLEAN as
'
DECLARE arrContent text[];
DECLARE serKeys text[];
countVal integer :=0;
result boolean;
searchkey text;
BEGIN
arrContent = $1::text[];
serKeys = $2::text[];
IF (count(cardinality(arrContent)) = 0 OR count(cardinality(serKeys)) = 0 OR cardinality(arrContent) = 0 OR cardinality(serKeys) = 0) THEN
RAISE NOTICE $quote$array is null$quote$;
RETURN TRUE;
END IF;
RAISE NOTICE $quote$after if condition$quote$;
FOREACH searchkey IN ARRAY serKeys
LOOP
result = arrayContains(arrContent, searchkey);
IF result = true THEN
RETURN TRUE;
END IF;
END LOOP;
RETURN FALSE;
EXCEPTION WHEN others THEN
RAISE NOTICE $quote$exception$quote$;
RETURN FALSE;
END;'
LANGUAGE plpgsql;
我们可以在 QueryBuilder 或 @Query 注释中调用上面的函数,如下所示
如果 QueryBuilder 示例输出如下所示
Specification<T> siteReqSpec1 = new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// TODO Auto-generated method stub
logger.info("getRBACResourceTagSpec entityName {} value {}", root.getModel().getName(), root.get(colName).getJavaType());
//return cb.isNotNull(root.get(colName));
//return cb.isMember(roleTagName, root.get(colName));
return cb.or(cb.isNull(root.get(colName)),
cb.isTrue(cb.function("arrayContains", Boolean.class, root.get(colName), cb.literal(roleTagName))));
}
};
如果是@Query 注释,如下所示
@Query("from DeviceworkFlowLite wf where wf.orgName = :organization and arrayContainsAny(rbac_resource_tags, :rbacResourceTags) = true")
Page<DeviceworkFlowLite> findAllByOrgNameAndRBACResourceTagsIn(@Param("organization")String organization, @Param("rbacResourceTags")String rbacResourceTags, Pageable pageable);
如果是jdbc SQL语句
private static final String GET_ALL_TEMPLATE_FILTER_BY_ORG =
"select name,rbac_resource_tags from template_metadata "
+ " and arrayContainsAny(rbac_resource_tags, ?) = true ";
ps.setString(4, jsonArrayRBACRoleResourceTag);