如何获取和/或设置谓词条件查询的参数?



我正在尝试重构我的 Spring 规范 (org.springframework.data.jpa.domain.Specification( 以便使用 JSR 310 类。换句话说,我的规格使用日期,而我想使用即时。

为了做到这一点,我想为规范创建单元测试。我的想法是获取生成的查询字符串,并在重构之前和之后比较它们。

如果与重构后相同,那么一切都应该很好。

但是,我的查询的参数始终为空。如果我尝试设置它们,我会得到一个非法论证。

Instant now = Instant.now();
Specification<Sp> sp = SpSpecification.betweenDates(now, now);
CriteriaBuilder cb = entityManagerFactory.getCriteriaBuilder();
CriteriaQuery<Sp> q = cb.createQuery(Sp.class);
Root<Sp> root = q.from(Sp.class);
Predicate p = sp.toPredicate(root, q, cb);
q.where(p);
TypedQuery<Sp> typedQuery = entityManagerFactory.createEntityManager().createQuery(q);
List<Sp> resultList = typedQuery.getResultList();
// doesn't show the parameter values
String queryString = typedQuery.unwrap(org.hibernate.Query.class).getQueryString();
// always empty
System.out.println(typedQuery.getParameters());
// ok get named parameters --> [param5, param0, param3, param4, param1, param2]
String[] namedParameters = typedQuery.unwrap(org.hibernate.Query.class).getNamedParameters();
// try and set one of them -> IllegalArgumentException (Unable to locate parameter registered with that name)
typedQuery.setParameter("param5", now);

也许你可以使用query.getNamedParameters()query.getParameterValue(namedParameter)来获取值.
由于我找不到一种使用 spring 数据specificationunrelated entities进行连接查询的方法,这不是由一对一或一对多关系定义的,我使用以下代码来组合规范(在这种情况下,它充当"字段汇编器"将表单字段转换为 where 子句(


@Override
public Page<TestData> find(Specification<TestData> testDataSpecification,
Specification patientSpecification,
Pageable page) {
String basicQuerystring = " from TestData t , Patient p  ";
StringBuffer finalQs = new StringBuffer();
finalQs.append(basicQuerystring);
String testDataAlias = "t";
Query testDataQuery = toQuery(testDataSpecification, TestData.class, testDataAlias);
String patientAlias = "p";
Query patientQuery = toQuery(patientSpecification, Patient.class, patientAlias);
String testDataWhere = getWhereQs(testDataQuery, testDataAlias);
String patientWhere = getWhereQs(patientQuery, patientAlias);
StringBuffer allWhere = new StringBuffer(" where t.patientCode=p.hospitalCode ");
allWhere.append(testDataWhere.length() > 0 ? (" and " + testDataWhere) : "");
allWhere.append(patientWhere.length() > 0 ? (" and " + patientWhere) : "");
finalQs.append(allWhere);
Map<String, Object> paramMap = new HashMap();
// page and sort
int pageSize = page.getPageSize();
long offset = page.getOffset();
String sortString = page.getSort().toString();
String countString = "select  count(*) " + finalQs.toString();
if (!"UNSORTED".equals(sortString)) {
finalQs.append(" sort by " + sortString);
}
javax.persistence.Query finalQuery = entityManager.createQuery(finalQs.toString());
finalQuery.setFirstResult((int) offset);
finalQuery.setMaxResults(pageSize);
// add params
if (testDataQuery != null) {
addParamValue(testDataAlias, testDataQuery, paramMap);
}
if (patientQuery != null) {
addParamValue(patientAlias, patientQuery, paramMap);
}
addAllParamsToQuery(paramMap, finalQuery);
List resultList = finalQuery.getResultList();
return PageableExecutionUtils.getPage(resultList, page, new LongSupplier() {
@Override
public long getAsLong() {
javax.persistence.Query countQuery = entityManager.createQuery(countString);
addAllParamsToQuery(paramMap, countQuery);
return (Long) countQuery.getSingleResult();
}
});
}
private Query toQuery(Specification specification, Class aClass, String classAlias) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery query = cb.createQuery(aClass);
Root<TestData> root = query.from(aClass);
root.alias(classAlias);
Predicate predicate = specification.toPredicate(root, query, cb);
return predicate == null ? null : entityManager.createQuery(query.where(predicate)).unwrap(Query.class);
}
private String getWhereQs(Query query, String entityAlias) {
if (query == null)
return "";
String queryString = query.getQueryString();
int containsWhere = queryString.indexOf("where");
String substring = "";
if (containsWhere != -1) {
substring = queryString.substring(containsWhere + "where".length());
}
return substring.replaceAll(":param", ":" + entityAlias + "param");
}
private void addParamValue(String testDataAlias, Query testDataQuery, Map<String, Object> paramMap) {
for (String namedParameter : testDataQuery.getNamedParameters()) {
paramMap.put(testDataAlias + namedParameter, testDataQuery.getParameterValue(namedParameter));
}
}
private void addAllParamsToQuery(Map<String, Object> paramMap, javax.persistence.Query finalQuery) {
for (Map.Entry<String, Object> each : paramMap.entrySet()) {
String paramName = each.getKey();
Object paramValue = each.getValue();
finalQuery.setParameter(paramName, paramValue);
}
}

最新更新