QueryDSL动态谓词

时间:2015-10-22 14:31:25

标签: spring spring-data-jpa querydsl

我需要QueryDSL查询的帮助。我在Spring Data JPA中使用这个库。 我的服务类:

@Service("tblActivityService")
public class TblActivityService implements AbstractService<TblActivity> {

@Resource
private TblActivityRepository tblActivityRepository;

@Override
public List<TblActivity> findAll(Predicate predicate) {
    return (List<TblActivity>) tblActivityRepository.findAll(predicate);
}
}

我有动态的过滤器列表:

@Entity
@Table(name = "sys_filters")
public class SysFilter implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "filter_id")
private Integer filterId;

@JoinColumn(name = "user_id", referencedColumnName = "user_id")
@ManyToOne(fetch = FetchType.EAGER)
private SysUser userId;

@Size(max = 45)
@Column(name = "table_name")
private String tableName;

@Size(max = 45)
@Column(name = "column_name")
private String columnName;

@Size(max = 45)
@Column(name = "condition")
private String condition;

@Size(max = 100)
@Column(name = "value")
private String value;


// getters & setters

}

我有列名(例如标题) 我有条件(例如==,!=,&gt; =等) - 我可以将它存储为符号或单词(等于等) 最后我有价值。

问题是“如何为我的服务动态生成谓词?” 表有大约25个字段。

谓词看起来像那样:

public BooleanExpression buildFilteredResult(List<SysFilter> filters) {
    //TODO do it!
    return QTblActivity.tblActivity.title.eq("Value"); 
// I need to do it dynamically for each filter in the list
}

问题是如何通过字符串值调用columnName。 你有什么建议吗?

3 个答案:

答案 0 :(得分:6)

对运算符使用映射过滤条件可能更容易

Map<String, Operator> operators = ImmutableMap.of(
  "==", Ops.EQ, "!=", Ops.NE, ">", Ops.GT, "<", Ops.LT,
  ">=", Ops.GOE, "<=", Ops.LOE);

Expressions.predicate(operators.get(condition), 
  stringPath, Expressions.constant(filterValue));

还要确保正确组合谓词

predicates.and(...)

返回一个新谓词并保持predicates不变。

也许BooleanBuilder就是你的目标?

答案 1 :(得分:1)

Spring spring / Fowler发布了一个更新的解决方案。如果您正在创建一个Web应用程序,您可以使用为您工作的querydsl Web支持 - 将get参数读入谓词,然后您可以使用来自控制器的此谓词 - 无需手动执行此操作 - 您可以根据特定数据类型或特定实体字段所需的搜索条件(相同,如...)自定义存储库。 see the documentation here

答案 2 :(得分:0)

我找到了解决方案:

public BooleanExpression buildFilteredResult(List<SysFilter> filters) {
    //TODO do it!

    QTblActivity qTblActivity = QTblActivity.tblActivity;
    BooleanExpression expression = qTblActivity.recordState;

    for (SysFilter filter : filters) {
        StringPath stringPath = new StringPath(qTblActivity, filter.getColumnName());
        switch (filter.getCondition()) {
            case "==":
                expression.and(stringPath.eq(filter.getValue()));
                break;
            case "!=":
                expression.and(stringPath.ne(filter.getValue()));
                break;
            case ">":
                expression.and(stringPath.gt(filter.getValue()));
                break;
            case "<":
                expression.and(stringPath.lt(filter.getValue()));
                break;
            case ">=":
                expression.and(stringPath.goe(filter.getValue()));
                break;
            case "<=":
                expression.and(stringPath.loe(filter.getValue()));
                break;
            default:
                break;
        }
    }

    return expression;

}