《从面试题来看源码》,#{}和${}的区别

面试题:#{}和${}的区别是什么?

#{}会对sql预编译处理,将#{}替换为占位符,字符串会变为'xxx'。${}则是直接替换变量

我们结合项目通过源码来看看两者是怎么解析的。这样不会无聊,也能加深印象。
在mybatis与spring集成的项目中,SqlSessionFactory由SqlSessionFactoryBean创建
以格式化delete from sys_attach where id = #{id}为例时序图是这样

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1


格式化后#{}会替换成 ?,表示占位符,预编译语句会使用PreparedStatement来处理

如果是delete from sys_attach where id = ${id},XMLScriptBuilder前面的过程都是一样的,主要是在parseScriptNode()方法中判断是静态sql,还是动态sql,动态sql是返回DynamicSqlSource对象,再执行sql语句的时候再将id赋值

  public SqlSource parseScriptNode() {
   //解析XNode成一系列SqlNode对象,并封装成MixedSqlNode对象,并会判断此SQL是否为动态
    MixedSqlNode rootSqlNode = parseDynamicTags(context);
    SqlSource sqlSource = null;
    if (isDynamic) {
     //是动态Sql
      sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
    } else {
      sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
    }
    return sqlSource;
  }
  //在运行时调用
  @Override
  public BoundSql getBoundSql(Object parameterObject) {
      //传入configuration和运行时的参数,创建DynamicContext对象
    DynamicContext context = new DynamicContext(configuration, parameterObject);
    //应用每个SqlNode,拼接Sql片段,这里只替换动态部分
   //此时context的sqlBuilder已经被解析具体的sql语句
    rootSqlNode.apply(context);
    //继续解析SQL,将#{}替换成?
    SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
    Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
    SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
    //创建BoundSql对象
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
      boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
    }
    return boundSql;
  }

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1

转载于:https://my.oschina.net/itsaysay/blog/3020436

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值