Mybatis-#{xxx}和${xxx}的区别&&PreparedStatement和Statement的区别

  • 预编译:数据库服务器在收到SQL语句后,会先去预编译缓存中查找该语句预编译的结果,如果找不到,则对SQL语句进行编译并将编译结果存入预编译缓存。
  • 客户端开启预编译,需要在建立连接时配置useServerPrepStmts=true&cachePrepStmts=true
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?useServerPrepStmts=true&amp;cachePrepStmts=true"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
  • 预编译的优点:在需要大量重复执行且只是参数不同的SQL语句,可以先将参数设置成占位符再交给数据库服务器进行预编译,这样后续的SQL语句不需要进行编译直接利用对应的编译结果进行参数设置再执行即可。

  • PreparedStatement:支持预编译和参数设置。在预编译/编译后再进行参数设置和执行。

  • Statement:不支持预编译和参数设置,直接发送SQL语句给数据库服务器进行编译和执行。

  • #{xxx}:当statementType等于默认的PREPARED时,Mybatis会将SQL语句中的#{xxx}换成占位符,再交给数据库服务器进行预编译/编译、参数设置和执行。当statementType等于STATEMENT时,会因占位符不能被识别而报错,因为Statement会直接进入编译和执行步骤,缺少参数设置方法。

  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select id, name, dept_id
    from employee
    where id = #{id,jdbcType=BIGINT}
  </select>

输出(statementType等于默认的PREPARED。要进行预编译的SQL语句里面的#{id}处用占位符 ? 替代)

2022-04-06 02:22:00,144 [main] DEBUG [com.wsh.mapper.EmployeeMapper.selectByPrimaryKey] - ==>  Preparing: select id, name, dept_id from employee where id = ?
2022-04-06 02:22:00,173 [main] DEBUG [com.wsh.mapper.EmployeeMapper.selectByPrimaryKey] - ==> Parameters: 1(Long)
2022-04-06 02:22:00,195 [main] DEBUG [com.wsh.mapper.EmployeeMapper.selectByPrimaryKey] - <==      Total: 1
  • ${xxx}:当statementType等于默认的PREPARED时,Mybatis首先将参数放入SQL语句,再交给数据库服务器进行预编译/编译、参数设置和执行,此处参数设置步骤没有任务。当statementType等于STATEMENT时,Mybatis首先将参数放入SQL语句,再交给数据库服务器进行编译和执行。 ${xxx}一般用于传输关于表或字段信息的值。
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select id, name, dept_id
    from employee
    where id = ${id,jdbcType=BIGINT}
  </select>

输出(发送给数据库服务器进行预编译的SQL语句里面的${id}直接替换为对应参数值,但由于statementType等于默认的PREPARED,仍然有参数设置的步骤)

2022-04-06 02:25:00,149 [main] DEBUG [com.wsh.mapper.EmployeeMapper.selectByPrimaryKey] - ==>  Preparing: select id, name, dept_id from employee where id = 1
2022-04-06 02:25:00,175 [main] DEBUG [com.wsh.mapper.EmployeeMapper.selectByPrimaryKey] - ==> Parameters: 
2022-04-06 02:25:00,199 [main] DEBUG [com.wsh.mapper.EmployeeMapper.selectByPrimaryKey] - <==      Total: 1

#{xxx}的优点:
防止SQL注入。在编译前用占位符替换#{xxx},得到的编译结果的语法逻辑是确定好的,SQL语句中的占位符只是充当参数的作用。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值