MyBatis ${} 与 #{}
一、看两种取值的效果
<select id="selectMyUserIdAndAge" resultType="myUser"> select * from myuser where id = #{arg0} and age = ${user.age} </select>
==> Preparing: select * from myuser where id = ? and age = 21 ==> Parameters: 7(Integer) <== Columns: id, name, age <== Row: 7, zhangsan, 21 <== Total: 1
#{}:以预编译的形式,将参数设置到 SQL 语句中。使用的是 PreparedStatement 防止 SQL 注入
${}:取出的值直接拼装在 SQL 语句中,会有安全问题
通常应该使用 #{} 来取值,更安全
官方文档
https://mybatis.org/mybatis-3/zh_CN/sqlmap-xml.html#Parameters
二、#{} 其它用法
可以在取值的时候指定一些参数:javaType、 jdbcType、 mode(存储过程)、 numericScale(保留几位小数)、resultMap、 typeHandler、 jdbcTypeName、 expression(表达式)
在参数数据为 null 时,有些数据库可能不能识别 mybatis 对 null 的默认处理。如 Oracle 会报错,因为 mybatis 对 null 的映射是原生 JDBC 的 OTHER 类型,oracle 不能正确处理
解决的话可以设置全局或指定单个参数
<!-- 设置 jdbcType --> <select id="selectMyUserIdAndAge" resultType="myUser"> select * from myuser where id = #{arg0,jdbcType=NULL} and age = ${user.age} </select>
<settings> <!-- 数据库字段下划线转 Bean 字段的驼峰命名 --> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 控制台打印SQL --> <setting name="logImpl" value="STDOUT_LOGGING" /> <!--全局设置为 NULL 时对应的 JDBC 类型--> <setting name="jdbcTypeForNull" value="NULL"/> </settings>
三、${} 其它用法
${} 既然是字符串拼接,那就可以放在原生 JDBC 不支持占位符的地方进行取值,如分表、排序等
<!-- 放在表名上 --> <select id="selectMyUserIdAndAge" resultType="myUser"> select * from ${user.name} where id = #{arg0} and age = ${user.age} </select>
四、JdbcType
org.apache.ibatis.type.JdbcType
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 TIME_WITH_TIMEZONE(Types.TIME_WITH_TIMEZONE), // JDBC 4.2 JDK8 TIMESTAMP_WITH_TIMEZONE(Types.TIMESTAMP_WITH_TIMEZONE); // JDBC 4.2 JDK8 public final int TYPE_CODE; private static Map<Integer, JdbcType> codeLookup = new HashMap<>(); 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); } }