MyBatis 参数处理

参数处理

单个参数

通过#{参数名}取出参数值

接口定义如下

public User getUserByUserName(String userName);

接口对应的 Mapper.xml 定义如下所示

<select id="getUserByUserName"
        parameterType="String"
        resultType="com.example.mybatis.entity.User">
    select
    id, username, user_email userEmail, user_city userCity, age
    from user
    where username = #{username}
</select>

多个参数

MyBatis会做特殊处理,会将你的多个参数封装成一个Map,keyparam1, param2,..., paramN,value为 value1,value2,...valueN,可以通过#{param1}来获取value1的值,#{paramN}来获取valueN的值。value1,value2,...valueN就是我们通过方法传递过来的值。

接口定义如下

public User getUserByIdAndUserName(Integer id, String username);

接口对应的 Mapper.xml 定义如下所示。 两个参数分别是 Integer 类型和 String 类型,类型不一致,此时 parameterType 可以省略 。

<select id="getUserByIdAndUserName"
        resultType="com.example.mybatis.entity.User">
    select
    id, username, user_email userEmail, user_city userCity, age
    from user
    where id = #{param1}
    and username = #{param2}
</select>

这里需要注意的是通过 #{param1} 和 #{param2} 来映射两个参数,以此类推,如果有第 3 个参数,则使用 #{param3} 来映射。

命名参数

MyBatis封装参数时由用户来指定Map的key.

接口定义如下

public User getUserByIdAndUserName(@Param("id")Integer id, @Param("username")String username);

接口对应的 Mapper.xml 定义如下所示

<select id="getUserByIdAndUserName"
        resultType="com.example.mybatis.entity.User">
    select
    id, username, user_email userEmail, user_city userCity, age
    from user
    where id = #{id}
    and username = #{username}
</select>

POJO

多个参数一个个写太麻烦了,这时候我们可以将参数列表进行封装,将封装对象作为 parameterType 的值。

接口定义如下

public User getUserByIdAndUserName(User user);

接口对应的 Mapper.xml 定义如下所示

命名参数:封装参数时指定Map的key,

<select id="getUserByIdAndUserName"
        parameterType="com.example.mybatis.entity.User"
        resultType="com.example.mybatis.entity.User">
    select
    id, username, user_email userEmail, user_city userCity, age
    from user
    where id = #{id}
    and username = #{username}
</select>

与多个参数的不同之处在于,这里是通过 #{属性名} 来映射参数对象的具体属性值的。

有时候为了方便,也可以直接使用Map来传递数据,但是使用Map会使得代码的可读性很差,一般不推荐使用这种方式。

特殊情况

如果参数类型是Collection(List,Set)类型或者是数组,MyBatis也会特殊处理

如果为Collection类型的,key为collection;如果为List类型的,key为list

public int addUserList(List<User> userList);

接口对应的 Mapper.xml 定义如下所示

<insert id="addUserList"
        parameterType="com.example.mybatis.entity.User"
        useGeneratedKeys="true"
        keyProperty="id">
    insert into user
    (username, user_email, user_city, age)
    values
    <foreach item="item"  collection="collection" separator=",">
        (#{item.username}, #{item.userEmail}, #{item.userCity}, #{item.age})
    </foreach>
</insert>

如果是数组类型,key为array

接口定义如下

public int addUserList(User[] userList);

接口对应的 Mapper.xml 定义如下所示

<insert id="addUserList"
        parameterType="com.example.mybatis.entity.User"
        useGeneratedKeys="true"
        keyProperty="id">
    insert into user
    (username, user_email, user_city, age)
    values
    <foreach item="item"  collection="array" separator=",">
        (#{item.username}, #{item.userEmail}, #{item.userCity}, #{item.age})
    </foreach>
</insert>

#{}与${}取值区别

#{}是以预编译的形式将参数设置到sql语句中,防止SQL注入,${}取出的值直接拼装在SQL语句中,会有安全问题。

不过有时你就是想直接在 SQL 语句中插入一个不转义的字符串。 比如,像 ORDER BY,你可以这样来使用

ORDER BY ${columnName}

这里 MyBatis 不会修改或转义字符串。

当 SQL 语句中的元数据(如表名或列名)是动态生成的时候,字符串替换将会非常有用。 举个例子,如果你想通过任何一列从表中 select 数据时,不需要像下面这样写:

@Select("select * from user where id = #{id}")
User findById(@Param("id") long id);

@Select("select * from user where name = #{name}")
User findByName(@Param("name") String name);

@Select("select * from user where email = #{email}")
User findByEmail(@Param("email") String email);

可以只写这样一个方法:

@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);

其中 ${column} 会被直接替换,而 #{value} 会被使用 ? 预处理。因此你就可以像下面这样来达到上述功能:

User userOfId1 = userMapper.findByColumn("id", 1L);
User userOfNameKid = userMapper.findByColumn("name", "kid");
User userOfEmail = userMapper.findByColumn("email", "noone@nowhere.com");

这个方法也同样适用于用来替换表名的情况。

#{}指定 jdbcType

只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。

为了以后可能的使用场景,MyBatis 通过内置的 jdbcType 枚举类型支持下面的 JDBC 类型。

BIT FLOAT CHAR TIMESTAMP OTHER UNDEFINED
TINYINT REAL VARCHAR BINARY BLOB NVARCHAR
SMALLINT DOUBLE LONGVARCHAR VARBINARY CLOB NCHAR
INTEGER NUMERIC DATE LONGVARBINARY BOOLEAN NCLOB
BIGINT DECIMAL TIME NULL CURSOR ARRAY

在我们数据为null的时候,有些数据库可能不能识别MyBatis对null的默认处理。比如Oracle,MyBatis对所有的null都映射成原生JDBC的OTHER类型,Oracle不能正确处理,但是MySQL却能处理。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!