组合模式来拼接SQL

84 阅读1分钟

序言

在MyBatis中实现组合模式来拼接SQL通常会涉及到使用SqlNode接口和其实现类,以及SqlNode的组合类。下面是一个简单的示例,展示如何使用组合模式来拼接SQL。

定义上下文

/**
 * 动态sql上下文
 * @author lty
 */
public class DynamicContext {

    private Map<String,Object> binding;

    private StringJoiner sqlBuilder = new StringJoiner(" ");

    public DynamicContext() {
        this(new HashMap<>());
    }

    public DynamicContext(Map<String,Object> binding){
        this.binding = binding;
    }

    /**
     * 获取绑定参数
     * @return
     */
    public Map<String, Object> getBinding() {
        return binding;
    }

    /**
     * 追加sql
     * @param sql
     */
    public void appendSql(String sql){
        sqlBuilder.add(sql);
    }

    /**
     * 获取sql
     * @return
     */
    public String getSql() {
        return sqlBuilder.toString().trim();
    }
}

定义接口

/**
 * SQL节点
 * @author lty
 */
public interface SqlNode {

    /**
     * 解析SQL
     * @param context 上下文
     */
    void parse(DynamicContext context);
}

普通静态节点

/**
 * 普通静态节点
 * @author lty
 */
public class StaticTextSqlNode implements SqlNode {

    private String text;

    public StaticTextSqlNode(String text) {
        this.text = text;
    }

    @Override
    public void parse(DynamicContext context) {
        context.appendSql(text);
    }
}

if节点

/**
 * if 标签的实现类
 * @author: lty
 */
public class IfSqlNode implements SqlNode {

    private String test;

    private SqlNode sqlNode;

    public IfSqlNode(String test, SqlNode contents) {
        this.test = test;
        this.sqlNode = contents;
    }

    @SneakyThrows
    @Override
    public void parse(DynamicContext context) {
        // 获取测试表达式的值
        Boolean value = (Boolean) Ognl.getValue(this.test, context.getBinding());
        if (value) {
            sqlNode.parse(context);
        }
    }
}

混合节点

/**
 * 混合节点
 * @author lty
 */
public class MixedSqlNode implements SqlNode {
    private List<SqlNode> sqlNodes;

    public MixedSqlNode(List<SqlNode> sqlNodes) {
        this.sqlNodes = sqlNodes;
    }

    @Override
    public void parse(DynamicContext context) {
        for (SqlNode sqlNode : sqlNodes) {
            sqlNode.parse(context);
        }
    }
}

测试

    public static void main(String[] args) {
        DynamicContext context = new DynamicContext(new HashMap<String, Object>() {
            {
                put("sex", "1");
            }
        });
        // 使用组合模式组合多个 SqlNode
        SqlNode mixedSqlNode = new MixedSqlNode(
                Lists.newArrayList(
                        new StaticTextSqlNode("SELECT * FROM table1"),
                        new StaticTextSqlNode("where id = 1"),
                        new IfSqlNode("sex!=1", new StaticTextSqlNode("and sex = '1'"))
                )
        );

        mixedSqlNode.parse(context);
        System.out.println("SQL: " + context.getSql());
        // SQL: SELECT * FROM table1 where id = 1 and sex = '1'
    }

使用组合模式组合多个 SqlNode,根据DynamicContext(动态上下文)去判断条件并根据传入的条件拼接SQL,实现动态SQL组合拼接