引數處理
單個引數
透過#{引數名}
取出引數值
介面定義如下
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,key
為param1, 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 協議》,轉載必須註明作者和本文連結