XxxMapper.xml-SQL映射文件
- 官方文檔
- 基本介紹
- 詳細說明
- 基本使用
- parameterType(輸入參數類型)
- 傳入HashMap
- resultMap(結果集映射)
官方文檔
文檔地址: https://mybatis.org/mybatis-3/zh_CN/sqlmap-xml.html
基本介紹
1.MyBatis
的真正強大在于它的語句映射(在XxxMapper.xml
配置), 由于它的異常強大, 如果拿它跟具有相同功能的JDBC
代碼進行對比, 你會立即發現省掉了將近95%
的代碼. MyBatis
致力于減少使用成本, 讓用戶能更專注于SQL
代碼.
2.SQL
映射文件常用的幾個頂級元素 (按照應被定義的順序列出) :
cache
- 該命名空間的緩存配置
cache-ref
- 引用其它命名空間的緩存配置
resultMap
- 描述如何從數據集結果集中加載對象, 是最復雜也是最強大的元素
parameterType
- 將會傳入這條語句的參數的類全限定名或別名
sql
- 可被其它語句引用的可重復的語句塊.
insert
- 映射插入語句
update
- 映射更新語句
delete
- 映射刪除語句
select
- 映射查詢語句
詳細說明
1.在原來的mybatis
項目中, 新建xml-mapper
子項目 [參考], 演示xml
映射器的使用
2.新建Module
后, 先創建需要的包, 再將需要的文件 / 資源拷貝過來(這里我們拷貝Monster.java
, resources/jdbc.properties
和 mybatis-config.xml
)
3.拷貝MonsterMapper.java
, MonsterMapper.xml
和 MonsterMapperTest.java
, 做一個比較 干凈的講解環境
基本使用
1.insert
, delete
, update
, select
這個我們在前面學習過, 分別對應增刪改查的方法和SQL
語句的映射
2.如何獲取到剛剛添加的Monster
對象的id
主鍵 [前面講解過了]
<insert id="addMonster" parameterType="Monster" useGeneratedKeys="true" keyProperty="id">INSERT INTO `monster` (`age`, `birthday`, `email`, `gender`, `name`, `salary`)VALUES (#{age}, #{birthday}, #{email}, #{gender}, #{name}, #{salary})
</insert>
parameterType(輸入參數類型)
●parameterType(輸入參數類型)
1.傳入簡單類型, 比如按照id
查Monster
(前面學過)
2.傳入POJO
類型, 查詢時需要有多個篩選條件
3.當有多個條件時, 傳入的參數就是Pojo
類型的Java
對象, 比如這里的Monster
對象
4.當傳入的參數類是String
時, 也可以使用 ${}
來接收參數
●parameterType-應用案例
案例1: 請查詢 id = 1
或者 name
= 大象精
的妖怪
案例2: 請查詢 name
中包含 “牛魔王” 的妖怪
●代碼實現
1.修改MonsterMapper.java
, 增加方法接口
public interface MonsterMapper {//通過id 或者 名字查詢public List<Monster> findMonsterByNameOrId(Monster monster);//查詢名字中含有牛魔王的妖怪public List<Monster> findMonsterByName(String name);
}
2.修改MonsterMapper.xml
<mapper namespace="com.zzw.mapper.MonsterMapper"><!--1. 配置/實現public List<Monster> findMonsterByNameOrId(Monster monster);2. 通過id 或者 名字查詢3. `id` = #{id} `id`表示表的字段名 #{id}中的id表示你傳入的Monster對象的屬性名--><select id="findMonsterByNameOrId" parameterType="Monster" resultType="Monster">SELECT * FROM `monster` WHERE `id` = #{id} OR `name` = #{name}</select><!--1. 配置/實現public List<Monster> findMonsterByName(Monster monster);2. 查詢名字中 含有 "牛魔王" 的妖怪 - 模糊查詢`3. 模糊查詢的使用 取值需要 ${value} 取值--><select id="findMonsterByName" parameterType="String" resultType="Monster">SELECT * FROM `monster` WHERE `name` LIKE '%${name}%'</select>
</mapper>
3.修改MonsterMapperTest.java
, 進行測試
public class MonsterMapperTest {//屬性private SqlSession sqlSession;private MonsterMapper monsterMapper;//編寫方法完成初始化@Beforepublic void init() {//獲取到sqlSessionsqlSession = MyBatisUtils.getSqlSession();//獲取到MonsterMapper對象 monsterMapper=class com.sun.proxy.$Proxy7 代理對象//, 底層是使用了動態代理機制, 后面我們自己實現mybatis底層機制時, 會講到monsterMapper = sqlSession.getMapper(MonsterMapper.class);System.out.println("monsterMapper=" + monsterMapper.getClass());}@Testpublic void findMonsterByNameOrId(){Monster monster = new Monster();monster.setId(1);monster.setName("大象精");List<Monster> monsters =monsterMapper.findMonsterByNameOrId(monster);for (Monster m : monsters) {System.out.println("m--" + m);}if (sqlSession != null) {sqlSession.close();}System.out.println("查詢成功");}@Testpublic void findMonsterByName() {List<Monster> monsters = monsterMapper.findMonsterByName("牛魔王");for (Monster monster : monsters) {System.out.println("monster--" + monster);}if (sqlSession != null) {sqlSession.close();}System.out.println("查詢成功");}
}
傳入HashMap
●傳入HashMap
(重點)
1.HashMap
傳入參數更加靈活, 比如可以靈活地增加查詢的屬性, 而不受限于Monster
這個Pojo
屬性本身
2.演示如何遍歷一個List<Map<String, Object>>
的數據類型
●傳入HashMap
- 應用實例1
要求: 聲明一個方法, 按傳入參數是HashMap
的方式, 查詢 id > 10
并且 salary > 40
的所有妖怪
1.修改MonsterMapper.java
, 增加方法接口
//查詢 id > 10 并且 salary > 40的所有妖怪
public List<Monster> findMonsterByIdAndSalary_ParameterHashMap(Map<String, Object> map);
2.修改MonsterMapper.xml
<!--
1. 配置/實現public List<Monster> findMonsterByIdAndSalary_ParameterHashMap(Map<String, Objects> map);
2. 查詢 id > 10 并且 salary > 40的所有妖怪
3. 如果是以map形式傳入參數, 當你這樣寫條件 `id` > #{id} 表示你的map 中有一個k-v 中 key為id
-->
<select id="findMonsterByIdAndSalary_ParameterHashMap" parameterType="map" resultType="Monster">SELECT * FROM `monster` WHERE `id` > #{id} AND `salary` > #{salary}
</select>
3.修改MonsterMapperTest.java
, 進行測試
@Test
public void findMonsterByIdAndSalary_ParameterHashMap() {Map<String, Object> map = new HashMap<>();map.put("id", 10);map.put("salary", 40);List<Monster> monsters =monsterMapper.findMonsterByIdAndSalary_ParameterHashMap(map);for (Monster monster : monsters) {System.out.println("monster--" + monster);}if (sqlSession != null) {sqlSession.close();}System.out.println("查詢成功");
}
●傳入和返回HashMap
- 應用實例2
要求: 將上面的方法改成返回參數也是HashMap
的類型
1.修改MonsterMapper.java
, 增加方法接口
//查詢 id > 10 并且 salary > 40, 要求傳入的參數是HashMap
public List<Map<String, Object>>findMonsterByIdAndSalary_ParameterHashMap_ReturnHashMap(Map<String, Object> map);
2.修改MonsterMapper.xml
<!--
1. 配置/實現public List<Map<String, Object>>findMonsterByIdAndSalary_ParameterHashMap_ReturnHashMap
2. 查詢 id > 10 并且 salary > 40, 要求傳入的參數是HashMap
-->
<select id="findMonsterByIdAndSalary_ParameterHashMap_ReturnHashMap" parameterType="map"resultType="map">SELECT * FROM `monster` WHERE `id` > #{id} AND `salary` > #{salary}
</select>
3.修改MonsterMapperTest.java
, 進行測試
@Test
public void findMonsterByIdAndSalary_ParameterHashMap_ReturnHashMap() {Map<String, Object> map = new HashMap<>();map.put("id", 10);map.put("salary", 40);List<Map<String, Object>> maps =monsterMapper.findMonsterByIdAndSalary_ParameterHashMap_ReturnHashMap(map);//取出返回的結果-以map的形式取出//回顧java基礎, map遍歷for (Map<String, Object> monsterMap : maps) {//System.out.println("monsterMap--" + monsterMap);//遍歷monsterMap(方式1), 取出屬性和對應值//Set<String> keySet = monsterMap.keySet();//for (String key : keySet) {// Object value = monsterMap.get(key);// System.out.println(key + "=>" + value);//}//遍歷monsterMap(方式2), 取出屬性和對應值Set<Map.Entry<String, Object>> entries = monsterMap.entrySet();for(Map.Entry<String, Object> entry : entries) {System.out.println(entry.getKey() + "=>" + entry.getValue());}System.out.println("==================================");}if (sqlSession != null) {sqlSession.close();}System.out.println("查詢成功");
}
resultMap(結果集映射)
●基本介紹
當實體類的屬性和表的字段不一致時, 我們可以通過resultMap
進行映射, 從而屏蔽實體類屬性名和表的字段名的不同.
●案例演示
1.創建表user
-- 創建表 user
CREATE TABLE `user` (`user_id` INT NOT NULL AUTO_INCREMENT,`user_email` VARCHAR(255) DEFAULT '',`user_name` VARCHAR(255) DEFAULT '',PRIMARY KEY (`user_id`)
)CHARSET=utf8
2.創建實體類com.zzw.entity.User
public class User {private Integer user_id;private String username;private String useremail;//setter, getter, toString方法
}
3.創建com.zzw.mapper.UserMapper.java
public interface UserMapper {//添加方法public void addUser(User user);//查詢所有Userpublic List<User> findAllUser();
}
4.創建com.zzw.mapper.UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--解讀1. 這是一個mapper xml 文件2. 該文件可以去實現對應的接口的方法3. namespace 指定該xml文件和哪個接口對應!!!
-->
<mapper namespace="com.zzw.mapper.UserMapper"><!--1. 配置/實現public void addUser(User user);2. 完成添加用戶的任務,注意這里--><select id="addUser" parameterType="User">INSERT INTO `user` (`user_email`, `user_name`)VALUES (#{useremail}, #{username})</select><!--1.配置/實現public List<User> findAllUser();2.返回所有User信息3.按照傳統的方式完成, 會出現什么問題?=> 如果對象屬性和表字段相同時, 就會設置值; 如果不同, 就會是默認值4.我們可以使用resultMap來解決5.resultMap: 表示我們要定義一個resultMap6.id="findAllUserMap" type="User" => id 就是程序員指定的resultMap id, 后面通過id可以使用它7.type="User", 就是你需要返回的對象類型8.result column="user_name" property="username": column="user_name" 表的字段名, property="username" 對象屬性名9.resultMap="findAllUserMap" 表示使用我們定義的 resultMap, 通過id關聯--><resultMap id="findAllUserMap" type="com.zzw.entity.User"><result column="user_name" property="username"/><result column="user_email" property="useremail"/></resultMap><select id="findAllUser" resultMap="findAllUserMap">SELECT * FROM `user`</select>
</mapper>
5.測試com.zzw.mapper.UserMapperTest
public class UserMapperTest {//屬性private SqlSession sqlSession;private UserMapper userMapper;//初始化@Beforepublic void init() {sqlSession = MyBatisUtils.getSqlSession();userMapper = sqlSession.getMapper(UserMapper.class);}@Testpublic void addUser() {User user = new User();user.setUsername("jack");user.setUseremail("jack@163.com");userMapper.addUser(user);//如果是增刪改, 需要提交事務if (sqlSession != null) {sqlSession.commit();sqlSession.close();}System.out.println("增加成功");}@Testpublic void findAllUser() {List<User> users = userMapper.findAllUser();for (User user : users) {System.out.println("user--" + user);}if (sqlSession != null) {sqlSession.close();}System.out.println("查詢成功");}
}
●注意事項和細節
1.解析表字段和對象屬性名不一致, 也支持使用字段別名
<!--使用表字段別名, 來解決表的字段名和對象屬性名, 不一致問題, 可以用, 但是我們仍然推薦使用resultMap-->
<select id="findAllUser" resultType="User">SELECT user_id, user_name as username, user_email as useremail FROM `user`
</select>
2.說明: 如果是MyBatis-Plus
處理就比較簡單, 可以使用 注解TableField
來解決實體字段名和表字段名不一致的問題, 還可以使用@TableName
來解決 實體類名和表名不一致的問題