NamedParameterJdbcTemplate使用OR运算符设置params并检查null

时间:2017-06-07 07:35:27

标签: java spring spring-jdbc named-parameters

class Request{
    private string f1;
    private string f2;
    private string f3;
}

我有以下查询

SELECT * FROM tbl WHERE f1  = 'val' OR f2  = 'val2' OR f3  = 'va3'
来自Request

字段可以是null。我需要创建NamedParameterJdbcTemplate查询并检查null的每个字段。

String query = "SELECT * FROM tbl"; 
if (request.getF1() !=null && !request.getF1().isEmpty()){
            query += ....
        } 

这是一个非常糟糕的解决方案......

我可以创建类似

的内容吗?
 Map<String, Object> namedParameters = new HashMap<>();

检查null的所有字段,如果不是null,请添加到地图并设置为查询?并设置运算符OR

1 个答案:

答案 0 :(得分:0)

在jdbc-template中你不能在框外做动态查询构建器(如果value为null,则将其从where部分中排除)。您应该创建自己的构建器。

如果你需要在一两个地方执行动态查询,你可以这样做:

只需将request.getF1() !=null && !request.getF1().isEmpty()重构为可读和可支持的内容,例如:

String select = SqlDynamicWhereSectionWithOrHelper.getInstance().
                applyIfPresentValue(fieldName1 , value1).
                applyIfPresentValue("" , null).
                applyIfPresentValue(fieldName2 , value2)
                .buildSqlWithWhere(GIVEN_SELECT);



public final class SqlDynamicWhereSectionWithOrHelper {
    private StringBuffer whereSqlQuery = new StringBuffer();
    public static final String WHERE = " where ";
    public static final String OR = " or ";
    private boolean whereNotPresent = true;

    private SqlDynamicWhereSectionWithOrHelper() {
    }

    public static SqlDynamicWhereSectionWithOrHelper getInstance() {
        return new SqlDynamicWhereSectionWithOrHelper();
    }

    public SqlDynamicWhereSectionWithOrHelper applyIfPresentValue(String fieldName, String fieldValue) {
        if (isNotEmpty(fieldValue) && isNotEmpty(fieldName)) {
            applyWhereOrOr(fieldName + "=" + wrapValue(fieldValue));
        }
        return this;
    }

    public String buildSqlWithWhere(String mainQueryWithoutWhere) {
        return mainQueryWithoutWhere + whereSqlQuery.toString();
    }

    //private section
    private String wrapValue(String fieldValue) {
        return "'" + fieldValue + "'";
    }

    private void applyWhereOrOr(String predicate) {
        String prefix = OR;
        if (whereNotPresent) {
            whereNotPresent = false;
            prefix = WHERE;
        }
        whereSqlQuery.append(prefix);
        whereSqlQuery.append(predicate);
    }

    //if you have apache common(or some other implementation) use  method from lib StringUtils.isEmpty(String value)
    private boolean isNotEmpty(String value) {
        return value != null && value.trim().length() > 0;
    }

}

并测试它

 private static final String GIVEN_SELECT = "select * from table";

 @Test
    public void testForWithParamsWithNull(){
        //set-up data
        String fieldName1 = "field1";
        String value1 = "value for field1";

        String fieldName2 = "field2";
        String value2 = "value for field2";

        StringBuffer expectedSelectBuffer = new StringBuffer(GIVEN_SELECT);
        expectedSelectBuffer.append(SqlDynamicWhereSectionWithOrHelper.WHERE);
        expectedSelectBuffer.append(fieldName1+"='"+value1+"'");
        expectedSelectBuffer.append(SqlDynamicWhereSectionWithOrHelper.OR);
        expectedSelectBuffer.append(fieldName2+"='"+value2+"'");
        String expectedSelect = expectedSelectBuffer.toString();

        //execution

        String resultSelect = SqlDynamicWhereSectionWithOrHelper.getInstance().
                applyIfPresentValue(fieldName1 , value1).
                applyIfPresentValue("" , null).
                applyIfPresentValue(fieldName2 , value2)
                .buildSqlWithWhere(GIVEN_SELECT);

        //verification
        assertThat(resultSelect , is(notNullValue()));
        assertThat(resultSelect ,equalTo(expectedSelect));
    }

此外,您可以尝试在SQL中修复它并检查为空,但如果您有大量数据要通过,则此技术会降低您的请求速度。

SELECT * FROM tbl WHERE (f1  = 'val' or f1 = null) OR (f2  = 'val2' or f2 = null ) OR (f3  = 'va3' or f3=null)