Mybatis实战 之 参数取值方式

Mybatis实战 之 参数取值方式

在Mybatis 的 Mapper接口文件时,我们可以使用两种方式来获取参数值即#{} 和 ${},下面我们将通过里来说明一下两者的区别。


实例

首先我们编写一条语句,然后分别使用#{} 和 ${} 分别取值。

  • sql

    select * from products where pid=${pid,jdbcType=INTEGER} and type=#{type,jdbcType=VARCHAR}
  • 编译后的语句

    Preparing: select * from products where pid=25 and type=?

    由上面的SQL 语句可以看出 ${} 和 #{} 都可以取出参数中的值但有以下区别:

    • 使用#{} 时,SQL入参使用的时预编译的方式,同时使用的是PreparedStatement,可以防止SQL注入

    • 使用${}时,SQL直接将参数值拼接在SQL中,因而不安全。

  • 使用场景
    既然两种方式都可以取值,那么一定可以得出的结论就是:各有各的优缺点。

    • #{} 的取值方式
      大多数场景中我们都应该使用#{}的取值方式来取值。

    • ${}的取值方式
      原生jdbc不支持占位符的地方我们就可以使用 使 {}
      来取值。比如今年时2017年,我们查询的表时products-2017表,若是2018则理应查询的时products-2018。那么此时我们便可以使用${}在取值。

      • 分表查询

        select * from products-${year} where pid=#{pid,jdbcType=INTEGER}
      • 排序查询

        <!--order 时传过来的排序条件-->
        select * from products order by   ${order}

扩展

  • #{} 更丰富的用法
    在使用#{} 的取值方式时 #{}在设置参数规则上还有更多用法。比如javaType、 jdbcType、 mode(存储过程)、 numericScale、resultMap、 typeHandler、 jdbcTypeName、 expression等。

  • 例子
    Mybatis 封装JDBCTYPE类型的源码

     *    Copyright 2009-2015 the original author or authors.
    package org.apache.ibatis.type;
    
    import java.sql.Types;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @author Clinton Begin
     */
    public enum JdbcType {
      /*
       * This is added to enable basic support for the
       * ARRAY data type - but a custom type handler is still required
       */
      ARRAY(Types.ARRAY),
      BIT(Types.BIT),
      TINYINT(Types.TINYINT),
      SMALLINT(Types.SMALLINT),
      INTEGER(Types.INTEGER),
      BIGINT(Types.BIGINT),
      FLOAT(Types.FLOAT),
      REAL(Types.REAL),
      DOUBLE(Types.DOUBLE),
      NUMERIC(Types.NUMERIC),
      DECIMAL(Types.DECIMAL),
      CHAR(Types.CHAR),
      VARCHAR(Types.VARCHAR),
      LONGVARCHAR(Types.LONGVARCHAR),
      DATE(Types.DATE),
      TIME(Types.TIME),
      TIMESTAMP(Types.TIMESTAMP),
      BINARY(Types.BINARY),
      VARBINARY(Types.VARBINARY),
      LONGVARBINARY(Types.LONGVARBINARY),
      NULL(Types.NULL),
      OTHER(Types.OTHER),
      BLOB(Types.BLOB),
      CLOB(Types.CLOB),
      BOOLEAN(Types.BOOLEAN),
      CURSOR(-10), // Oracle
      UNDEFINED(Integer.MIN_VALUE + 1000),
      NVARCHAR(Types.NVARCHAR), // JDK6
      NCHAR(Types.NCHAR), // JDK6
      NCLOB(Types.NCLOB), // JDK6
      STRUCT(Types.STRUCT),
      JAVA_OBJECT(Types.JAVA_OBJECT),
      DISTINCT(Types.DISTINCT),
      REF(Types.REF),
      DATALINK(Types.DATALINK),
      ROWID(Types.ROWID), // JDK6
      LONGNVARCHAR(Types.LONGNVARCHAR), // JDK6
      SQLXML(Types.SQLXML), // JDK6
      DATETIMEOFFSET(-155); // SQL Server 2008
    
      public final int TYPE_CODE;
      private static Map<Integer,JdbcType> codeLookup = new HashMap<Integer,JdbcType>();
    
      static {
        for (JdbcType type : JdbcType.values()) {
          codeLookup.put(type.TYPE_CODE, type);
        }
      }
    
      JdbcType(int code) {
        this.TYPE_CODE = code;
      }
    
      public static JdbcType forCode(int code)  {
        return codeLookup.get(code);
      }
    
    }
    

    在使用Mysql作为DB时,如果穿过来的参数为null,那么Mybatis 会将null 解析并定义为jdbcType=OTHER,同时Mysql 数据库支持OTHER并将其视为null。

    但使用Oracle作为DB时,如果传过来的参数为null时,mybatis也会将null解析并定义为jdbcType=OTHER,但Oracle并不支持jdbcType=OTHER这个数据类型。

  • 解决办法
    在Mybatis的配置文件中的settings中做一下设置:

    <setting name="jdbcTypeForNull" value="NULL"/>

    统一将参数值为空的参数的jdbcType统一设置成为为 jdbcType=NULL,这样Mysql和Oracle都将支持该种jdbcType。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值