Mybatis SQL Parameters

作者:範宗雲 来源:原创 发布时间:2015-04-26 归档:mybatis

环境 : JDK 7 Mybatis 3.2.7 Maven 3 Junit 4.11 Spring 4.1.5 Eclipse Luna
参数语法
mybatis sql 参数的语法有两种 :#{} 与 ${}
${} 是不经任何处理将传入的值直接替换掉参数变量拼接到 SQL 语句中。如 :
SELECT * FROM USER WHERE name = ${name} AND password = ${password}
若传入 name : admin, password : admin, 则最终的 SQL 语句为 :
SELECT * FROM USER WHERE name = admin AND password = admin
这样容易遭到恶意的 SQL 攻击, 如若传入的值为 name : 1 or 1 = 1, password : 1 or 1 = 1, 则最终的 SQL 语句为 :
SELECT * FROM USER WHERE name = 1 or 1 = 1 AND password = 1 or 1 = 1
无论如何, 这条 SQL 总是会返回有效数据的, 除非数据库没有数据。
#{} 是经过预编译处理, 传入到 SQL 参数中的值是安全的。
SELECT * FROM USER WHERE name = #{name} AND password = #{password}
若传入 name : admin, password : admin, 则最终的 SQL 语句为 :
SELECT * FROM USER WHERE name = ? AND password = ?
它相当于 :
          String sql = "SELECT * FROM USER WHERE name = ? AND password = ?";
          PreparedStatement preparedStatement = conn.prepareStatement(sql);
          preparedStatement.setString(1, "admin");
          preparedStatement.setString(2, "admin");
          
但有时候 SQL 的参数只能用 ${} 语法, 不能使用 #{} 语法, 例如 ORDER BY
SELECT * FROM USER ORDER BY ${regTime}
参数类型
如果传入的参数是一个简单的数据类型, 如原生类型、包装类型、String 等没有对象属性的数据类型。这种数据类型的参数与 SQL 语句中的参数名称无关, 它将完全由传入的参数值来替代。例如 :
            <select id="queryById" parameterType="int" resultType="User">
              SELECT * FROM USER WHERE id = #{id}
            </select>
          
这里的参数类型设成了 int, 那么, SQL 中的参数名称可以是任意串的内容, 你可以写成 #{userId} 等, 不是非得写成 #{id}, 只不过我们习惯了这样做。
如果传入的参数是一个复杂的对象, 如 :
            <insert id="save" parameterType="User">
              INSERT INTO USER(name, password) VALUES(#{name}, #{password})
            </insert>
          
这里的参数类型设成了 User, 那么, SQL 中的 #{name}, #{password} 参数, 会根据参数名 name, password 去 User 对象中查找属性, 然后将它们的值传入到预处理语句中, 如果从传入的对象中查找不到相应的属性, 将会报出错误。
JAVA 与 SQL 数据类型映射
javaType 可以指定参数的数据类型, jdbcType 用于指定数据库中的数据类型, 如 :
            <insert id="save" parameterType="User">
              INSERT INTO USER(name, password) VALUES(#{name, javaType=string, jdbcType=VARCHAR}, 
                #{password, javaType=string, jdbcType=CHAR})
            </insert>
          
实际上, 我们很少这样手工的去设定它们之间的映射关系, 它们通常可以从传入的参数中被推定出来。