spring数据jpa动态查询,其中有IN子句

时间:2017-06-15 15:21:37

标签: spring spring-data-jpa

我想在spring数据jpa中创建动态查询。做了很多搜索我可以实现它,但是当我在where子句中添加IN运算符时遇到了一个问题。我需要检查id IN(longlist) 这是我的实体类

@Entity
@Table(name = "view_detail")
public class ViewDetailDom {

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;

private String name;

@Column(name = "user_id")
private Long userId;

private String description;

这是规范构建器类和规范类

public class ViewDetailSpecificationsBuilder {

private final List<SearchCriteria> params;

public ViewDetailSpecificationsBuilder() {
    params = new ArrayList<SearchCriteria>();
}

public ViewDetailSpecificationsBuilder with(String key, Operation operation, Object value) {
    params.add(new SearchCriteria(key, operation, value));
    return this;
}

public Specification<ViewDetailDom> build() {
    if (params.size() == 0) {
        return null;
    }

    List<Specification<ViewDetailDom>> specs = new ArrayList<Specification<ViewDetailDom>>();
    for (SearchCriteria param : params) {
        specs.add(new ViewDetailSpecification(param));
    }

    Specification<ViewDetailDom> result = specs.get(0);
    for (int i = 1; i < specs.size(); i++) {
        result = Specifications.where(result).and(specs.get(i));
    }
    return result;
}

}



public class ViewDetailSpecification implements Specification<ViewDetailDom> {

private SearchCriteria criteria = new SearchCriteria();

public ViewDetailSpecification(SearchCriteria searchCriteria) {
    this.criteria.setKey(searchCriteria.getKey());
    this.criteria.setOperation(searchCriteria.getOperation());
    this.criteria.setValue(searchCriteria.getValue());
}

@Override
public Predicate toPredicate(Root<ViewDetailDom> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
    String value = criteria.getValue().toString().replaceAll(" ", "%");
    if (criteria.getOperation() != null && criteria.getOperation() != Operation.DEFAULT) {
        if (criteria.getOperation() == Operation.GREATHERTHANEQUALTO) {
            return builder.greaterThanOrEqualTo(root.<String>get(criteria.getKey()), value);
        } else if (criteria.getOperation() == Operation.LESSTHANEQUALTO) {
            return builder.lessThanOrEqualTo(root.<String>get(criteria.getKey()), value);
        } else if (criteria.getOperation() == Operation.EQUAL) {
            return builder.equal(root.<String>get(criteria.getKey()), value);
        } else if (criteria.getOperation() == Operation.IN) {
            Path<Long> view = root.<Long>get(criteria.getKey());
            return view.in(criteria.getValue());
        }
    } else {
        if (root.get(criteria.getKey()).getJavaType() == String.class) {
            return builder.like(builder.lower(root.<String>get(criteria.getKey())),
                    "%" + value.toLowerCase() + "%");
        } else {
            return builder.equal(root.get(criteria.getKey()), value);
        }
    }
    return null;
}

}

此方法创建规范构建器:

public ViewDetailSpecificationsBuilder createSearchSpecifications(ViewSearch view) {
    ViewDetailSpecificationsBuilder builder = new ViewDetailSpecificationsBuilder();
    if (StringUtils.isNotBlank(view.getName())) {
        builder.with("name", Operation.DEFAULT, view.getName());
    }
    if (StringUtils.isNotBlank(view.getDescription())) {
        builder.with("description", Operation.DEFAULT, view.getDescription());
    }

    return builder;
}

最后我这样做了:

ViewDetailSpecificationsBuilder builder = createSearchSpecifications(view);
builder.with("userId", Operation.DEFAULT, userSessionHelper.getUserId());
builder.with("id", Operation.IN, viewids);
Specification<ViewDetailDom> spec = builder.build();
viewDetailDao.findAll(spec);

但我收到以下错误:

"Unaware how to convert value [[5, 7, 8] : java.util.ArrayList] to requested type [java.lang.Long]; nested exception is java.lang.IllegalArgumentException: Unaware how to convert value [[5, 7, 8] : java.util.ArrayList] to requested type [java.lang.Long]"

2 个答案:

答案 0 :(得分:0)

我已经用这种方式解决了这个问题:

ViewDetailSpecification class:

if (criteria.getOperation() == Operation.IN) {
            final List<Predicate> orPredicates = new ArrayList<Predicate>();
            List<Long> viewIds = (List<Long>) criteria.getValue();
            for (Long viewid : viewIds) {
                orPredicates.add(builder.or(builder.equal(root.<String>get(criteria.getKey()), viewid)));
            }
            return builder.or(orPredicates.toArray(new Predicate[orPredicates.size()]));
        }

答案 1 :(得分:0)

在kotlin中,我有相同的错误,我将ArrayList更改为Array,使用以下代码:

fun values(): Array<String> {
    val elems = arrayListOf<String>()
    return elems.toTypedArray()
}

尝试将ArrayList转换为数组,有关Java,请参见:make arrayList.toArray() return more specific types