在MyBatis开发中,参数变量的动态预处理常常散落在业务代码中,导致逻辑重复且难以维护。借助Lambda表达式,我们可以将预处理行为抽象为函数,使动态SQL的组装更简洁。
传统预处理方式的问题
通常我们会写一个方法来拼接参数,例如根据字段是否为空决定是否加入查询条件:
public String buildSql(User user) {
StringBuilder sql = new StringBuilder("SELECT * FROM user WHERE 1=1");
if (user.getName() != null) {
sql.append(" AND name = '").append(user.getName()).append("'");
}
if (user.getAge() != null) {
sql.append(" AND age = ").append(user.getAge());
}
return sql.toString();
}
这种方式在参数多时变得难以阅读,且预处理规则无法复用。
使用Lambda封装预处理逻辑
我们可以定义一个函数式接口,用Lambda表示单个参数的预处理动作:
@FunctionalInterface
public interface ParamHandler<T> {
void handle(StringBuilder sql, String column, T value);
}
然后提供一个工具类,接收Lambda列表统一处理:
public class SqlBuilder {
public static <T> void appendIfPresent(StringBuilder sql, String column, T value, ParamHandler<T> handler) {
if (value != null) {
handler.handle(sql, column, value);
}
}
}
在MyBatis Provider中应用
结合@SelectProvider使用Lambda优化动态SQL:
public class UserSqlProvider {
public String query(User user) {
StringBuilder sql = new StringBuilder("SELECT * FROM user WHERE 1=1");
SqlBuilder.appendIfPresent(sql, "name", user.getName(), (s, c, v) -> s.append(" AND ").append(c).append(" = '").append(v).append("'"));
SqlBuilder.appendIfPresent(sql, "age", user.getAge(), (s, c, v) -> s.append(" AND ").append(c).append(" = ").append(v));
return sql.toString();
}
}
Mapper接口引用该Provider:
@Mapper
public interface UserMapper {
@SelectProvider(type = UserSqlProvider.class, method = "query")
List<User> query(User user);
}
优势总结
- 预处理逻辑以Lambda形式内聚,避免重复if判断
- 每个字段的规则清晰独立,便于单测
- Provider方法更短,可读性明显提升
注意:示例为防注入简化写法,生产环境应使用MyBatis的#{}参数绑定而非字符串拼接。