前言
接着上一篇Mybatis入門繼續,上一篇主要示範了Mybatis的基本操作,對資料庫的增删改查,但是在實際項目中用到的Mybatis知識點要遠多于這些基本操作,這篇将示範一些Mybatis的更加常用的用法。
知識點彙總
建立項目,基本環境都如上篇,Maven的pom.xml中添加jUnit依賴。
Insert擷取主鍵的值
Mapper.xml的Insert節點添加useGeneratedKeys,keyProperty即可。
KeyProperty:(僅對 insert 和 update 有用)唯一标記一個屬性,MyBatis 會通過 getGeneratedKeys 的傳回值或者通過 insert 語句的 selectKey 子元素設定它的鍵值,預設:unset。如果希望得到多個生成的列,也可以是逗号分隔的屬性名稱清單。
UseGeneratedKeys:僅對 insert 和 update 有用)這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由資料庫内部生成的主鍵(比如:像 MySQL 和 SQL Server 這樣的關系資料庫管理系統的自動遞增字段),預設值:false。
在
Mybaitis 入門教程的項目, Mapper.xml檔案中
修改内容為下:
<insert id="insertBlog" parameterType="Blog"
keyProperty="id"
useGeneratedKeys="true"
>
INSERT INTO Blog (id,title) VALUES (#{id},#{title})
</insert>
此時資料庫内容:

程式運作前資料庫内容
測試程式:
@Test
public void test1(){
InputStream inputStream = null;
SqlSession sqlSession = null;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory mSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = mSqlSessionFactory.openSession();
Blog blog = new Blog("擷取主鍵的值");
sqlSession.insert("me.aihe.dao.BlogMapper.insertBlog",blog);
// 檢測是否将插入資料的主鍵傳回
System.out.println(blog.getId());
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
運作結果
運作程式之後資料庫内容
注意:還有一種實作方式是在insert内部添加<SelectKey>節點,這裡就不再示範。
SQL映射檔案參數分析
在Mapper.xml檔案中,SQL語句裡我們可以傳入對象,或傳入其它參數。
當我們以如下方式傳遞參數時:
// 這是在UserMapp.java檔案
int insertByParam(int id,String name, String email);
//UserMapper.xml檔案中
<insert id="insertByParam">
INSERT INTO User (id,name,email) VALUE (#{id},#{name},#{email})
</insert>
測試程式如下:
@Test
public void test2(){
InputStream inputStream = null;
SqlSession sqlSession = null;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory mSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = mSqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userMapper.insertByParam(2,"Gao","[email protected]");
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
這個時候程式運作會出現如下錯誤,提示我們找不到參數。
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg2, arg1, arg0, param3, param1, param2]
解決方法:四種任選其一
- 修改UserMapp.java檔案添加@Param注解,即可
int insertByParam(@Param("id") int id,@Param("name") String name, @Param("email") String email);
- 修改UserMapper.xml檔案,修改為param*類型如下
<insert id="insertByParam" >
INSERT INTO User (id,name,email) VALUE (#{param1},#{param2}, #{param3})
</insert>
- 将參數換為對象,如下
// UserMapper.java修改為如下
int insertByPoDo(User user);
//UserMapper.java修改為下
<insert id="insertByPoDo"
parameterType="User"
>
INSERT INTO User (name,email) VALUE (#{name},#{email})
</insert>
//Test檔案修改為如下
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User("leishen","[email protected]");
userMapper.insertByPoDo(user);
- 将參數轉為Map對象。
int insertByMap(Map<String,Object> map);
//xml
<insert id="insertByMap">
INSERT INTO User (name,email) VALUE (#{name},#{email})
</insert>
//Test
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
HashMap<String,Object> map = new HashMap<String, Object>();
map.put("name","test");
map.put("email","[email protected]");
userMapper.insertByMap(map);
sqlSession.commit();
一般來說,模型與業務相關傳入POJO對象,與業務無關就傳入Map對象。
注意:關于參數封裝原理部分請檢視MapperMethod.java,ParamNameResolve.java
SQL語句中$與#的差別
預設情況下,使用#{}格式的文法會導緻 MyBatis 建立預處理語句屬性并安全地設定值(比如?)。這樣做更安全,更迅速,通常也是首選做法,不過有時你隻是想直接在 SQL 語句中插入一個不改變的字元串。比如,像 ORDER BY,你可以這樣來使用:
ORDER BY ${columnName}
這裡 MyBatis 不會修改或轉義字元串。
注意:** 以這種方式接受從使用者輸出的内容并提供給語句中不變的字元串是不安全的,會導緻潛在的 SQL 注入攻擊,是以要麼不允許使用者輸入這些字段,要麼自行轉義并檢驗。**
$是字元串替換,#會進行預編譯
擷取清單資料
// UserMapper接口
List<User> getUserByEmail(@Param("email") String email);
// UserMaper.xml
<select id="getUserByEmail" resultType="me.aihe.dao.User">
SELECT * FROM User WHERE email LIKE #{email}
</select>
//測試檔案
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> result = userMapper.getUserByEmail("aihe%");
System.out.println(result);
最終輸出内容
擷取清單資料結果
擷取Map資料
//UserMapeer接口檔案
Map<String,Object> getUserMapById(@Param("id") Integer id);
//UserMapper.xml檔案
<select id="getUserMapById" resultType="java.util.Map">
SELECT * FROM User WHERE id = #{id}
</select>
//測試程式
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
Map result = userMapper.getUserMapById(2);
System.out.println(result);
測試輸出結果
擷取Map資料結果
擷取Map映射的多組資料
這個和擷取清單很類似了,隻不過把數組都封裝到一個Map中去了
// UserMapper接口檔案
@MapKey("id")
Map<Integer,User> getUserMapLikeemail(@Param("email") String email);
// UserMapper.xml檔案
<select id="getUserMapById" resultType="java.util.Map">
SELECT * FROM User WHERE id = #{id}
</select>
// 測試檔案
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
Map result = userMapper.getUserMapLikeemail("%aihe%");
System.out.println(result);
程式輸出
**注意: 注解@MapKey指定的是以資料庫表中的那一列作為Map結果的key。
使用ResultMap來映射結果資料
// UserMapper接口
User getUserMapByIdThroughResultMap(@Param("id") Integer id);
// UserMapper.xml檔案
//Id辨別的是查詢結果中的主鍵是那一列,對應的User屬性是什麼
<resultMap id="MyResultMap" type="User">
<id column="id" property="id" />
<result property="email" column="email" />
<result property="name" column="name" />
</resultMap>
<select id="getUserMapByIdThroughResultMap" resultMap="MyResultMap">
SELECT * FROM User WHERE id = #{id}
</select>
//測試檔案
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserMapByIdThroughResultMap(2);
System.out.println(user);
輸出結果
ResultMap映射結果資料
總結
本文主要講解了幾個Mybatis日常使用中經常用到的幾個知識點,擷取主鍵,參數映射,及$與#符号的差別,最後示範一些各種擷取資料庫中結果的方式。