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
答案 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)