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
来解决 实体类名和表名不一致的问题