Insight mybatis xml 动态sql解析

来源:互联网 发布:部门信息表sql 编辑:程序博客网 时间:2024/06/03 18:47

一. mybatis 动态sql疑问

1. 占位符${foo},#{foo}怎样解析的?

2. xml 动态sql是怎样翻译的?

二. Insight

首先需要明确runtime ,执行的过程:

// select查询执行过程public  List selectList(String statement, Object parameter, RowBounds rowBounds) {    try {        // 1. 根据mapper 方法名称,从configuration取出对应的statement 主要就是动态sql xml片段        MappedStatement ms = configuration.getMappedStatement(statement);        // 2. 根据配置的statement,执行查询,返回结果集        List result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);        return result;    } // ...}// 解析动态sql,执行sqlpublic  List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {    // 动态sql就是在这个阶段完成解析,形成标准的sql 语句, eg: select * from dual where id = ?    BoundSql boundSql = ms.getBoundSql(parameter);    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);}
然后看解析的核心实现:

// xml 动态sql核心实现,更具体的类参考SqlNode、SqlSource其他实现类public BoundSql getBoundSql(Object parameterObject) {    DynamicContext context = new DynamicContext(configuration, parameterObject);    //1. 纯文本解析,包括 TextSqlNode, ForEachSqlNode, IfSqlNode, VarDeclSqlNode, TrimSqlNode, WhereSqlNode, SetSqlNode, ChooseSqlNode    // 其中${foo} 表达式就是在TextSqlNode 实现,@see new GenericTokenParser("${", "}", new BindingTokenParser(context))    rootSqlNode.apply(context);    SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);    Class parameterType = parameterObject == null ? Object.class : parameterObject.getClass();    //2. 带有关联参数解析,prepareStatement 中用到的parameterMappings    // 其中#{foo} 表达式就是在此处实现,@see new GenericTokenParser("#{", "}", handler);    SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);        return boundSql;}

解疑完毕。

三.参考

各个动态sql节点的解析器

put("trim", new TrimHandler());put("where", new WhereHandler());put("set", new SetHandler());put("foreach", new ForEachHandler());put("if", new IfHandler());put("choose", new ChooseHandler());put("when", new IfHandler());put("otherwise", new OtherwiseHandler());put("bind", new BindHandler());


原创粉丝点击