带你了解什么是XxxxMapper.xml-SQL 映射文件

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 带你了解什么是XxxxMapper.xml-SQL 映射文件

XxxxMapper.xml-SQL 映射文件


官方文档


文档地址: https://mybatis.org/mybatis-3/zh/sqlmap-xml.html


XxxMapper.xml-基本介绍


MyBatis 的真正强大在于它的语句映射(在XxxMapper.xml 配置), 由于它的异常强大, 如果拿它跟具有相同功能的JDBC 代码进行对比,你会立即发现省掉了将近95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于SQL 代码。


SQL 映射文件常用的几个顶级元素(按照应被定义的顺序列出):


cache – 该命名空间的缓存配置。
cache-ref – 引用其它命名空间的缓存配置。
 resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
parameterType - 将会传入这条语句的参数的类全限定名或别名
sql – 可被其它语句引用的可重用语句块
insert – 映射插入语句。
update – 映射更新语句。
delete – 映射删除语句。
select – 映射查询语句。


XxxMapper.xml-详细说明


新建Module xml-mapper


在原来的项目中,新建xml-mapper 项目演示xml 映射器的使用。

新建Module 后,先创建需要的包,再将需要的文件/资源拷贝过来(这里我们拷贝Monster.java、resources/jdbc.properties 和mybatis-config.xml)。

创建MonsterMapper.java MonsterMapper.xml 和MonsterMapperTest.java


代码准备


因为是一个新的Module ,我们需要把需要的文件/资源从前面拷贝过来。

创建Monster.java。


这里的get set 和tostring大家自己生成一下或者使用注解@set @get 和快捷键生成tostring。

/**
 * Monster 和 monster表有对应关系
 * 体现OOP
 */
//解读
//1. 一个普通的Pojo类
//2. 使用原生态的sql语句查询结果还是要封装成对象
//3. 这里的实体类属性名和表名字段保持一致。
public class Monster {
    //属性-和表字段有对应关系
    private Integer id;
    private Integer age;
    private String name;
    private String email;
    private Date birthday;
    private double salary;
    private Integer gender;
    public Monster() {
    }
    public Monster(Integer id, Integer age, String name, String email, Date birthday, double salary, Integer gender) {
        this.id = id;
        this.age = age;
        this.name = name;
        this.email = email;
        this.birthday = birthday;
        this.salary = salary;
        this.gender = gender;
    }
}


MonsterMapper .xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--解读
1. 这是一个mapper xml 文件
2. 该文件可以去实现对应的接口的方法
3. namespace 指定该xml文件和哪个接口对应!!!
-->
<mapper namespace="com.nlc.mapper.MonsterMapper">
</mapper>


MonsterMapperTest.java

public class MonsterMapperTest {
    //属性
    private SqlSession sqlSession;
    private MonsterMapper monsterMapper;
    //初始化
    @Before
    public void init() {
        sqlSession = MyBatisUtils.getSqlSession();
        monsterMapper = sqlSession.getMapper(MonsterMapper.class);
        System.out.println("monsterMapper=" + monsterMapper.getClass());
    }
}


jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8//注意这里填自己的
jdbc.user=root
jdbc.pwd=123456//注意这里填自己的密码


mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--引入外部的jdbc.properties-->
    <properties resource="jdbc.properties"/>
    <!--配置MyBatis自带的日志输出-查看原生的sql-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--配置别名-->
    <typeAliases>
        <!--<typeAlias type="com.nlc.entity.Monster" alias="Monster"/>
    给Monster类配置别名,只有Monster类的方法可以使用
  -->
        <!--
            如果一个包下有很多的类,我们可以直接引入包,
    这样该包下面的所有类名,可以直接使用
        -->
        <package name="com.nlc.entity"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <!--配置事务管理器-->
            <transactionManager type="JDBC"/>
            <!--配置数据源
            解读
            1. 我们使用外部的properties文件来设置相关的值
            2. 这个属性文件,需要统一的放在 resources目录/类加载路径
            -->
            <dataSource type="POOLED">
                <!--配置驱动-->
                <!--<property name="driver" value="com.mysql.jdbc.Driver"/>-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--配置连接mysql-url
                解读:
                1. jdbc:mysql 协议
                2. 127.0.0.1:3306 : 指定连接mysql的ip+port
                3. mybatis: 连接的DB
                4. useSSL=true 表示使用安全连接
                5. &amp; 表示 & 防止解析错误
                6. useUnicode=true : 使用unicode 作用是防止编码错误
                7. characterEncoding=UTF-8 指定使用utf-8, 防止中文乱码
                8. 温馨提示:不要背,直接使用即可
                -->
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.pwd}"/>
            </dataSource>
        </environment>
    </environments>
    <!--说明
    1. 这里我们配置需要关联的Mapper.xml
    2. 这里我们可以通过菜单 Path from source root
    -->
    <mappers>
        <!--<mapper resource="com/nlc/mapper/MonsterMapper.xml"/>-->
        <!--解读
           1. 如果是通过注解的方式,可不再使用 MonsterMapper.xml
           2. 但是需要在mybatis-config.xml注册/引入含注解的类
           3. 如果没有引入,不能使用
        -->
        <!--
            解读
            1. 当一个包下有很多的Mapper.xml文件和基于注解实现的接口时,
               为了方便,我们可以以包方式进行注册
           2. 将下面的所有xml文件和注解接口 都进行注册
        -->
        <package name="com.nlc.mapper"/>
    </mappers>
</configuration>


基本使用


  1. insert、delete、update、select 这个我们在前面讲解过,分别对应增删改查的方法和SQL语句的映射.
  2. 如何获取到刚刚添加的Monster 对象的id 主键[前面使用过了]

c58f54998d6d4cd8a9c4d7016712afcb.png


parameterType(输入参数类型)


parameterType(输入参数类型)


  1. 传入简单类型,比如按照id 查Monster
  2. 传入POJO 类型,查询时需要有多个筛选条件
  3. 当有多个条件时,传入的参数就是Pojo 类型的Java 对象,比如这里的Monster 对象
  4. 当传入的参数类是String 时,也可以使用${} 来接收参数


parameterType-应用案例


案例1:请查询id = 1 或者name = ‘白骨精’ 的妖怪

案例2:请查询name 中包含"牛魔王" 的妖怪


修改MonsterMapper.java, 增加方法接口

//通过id 或者名字查询
public List<Monster> findMonsterByNameORId(Monster monster);
//查询名字中含义'精'妖怪
public List<Monster> findMonsterByName(String name);


  1. 修改MonsterMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--解读
1. 这是一个mapper xml 文件
2. 该文件可以去实现对应的接口的方法
3. namespace 指定该xml文件和哪个接口对应!!!
-->
<mapper namespace="com.nlc.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(String name);
    2. 请查询 name 中 包含 "牛魔王" 的妖怪 - 是模糊查询
    3. 模糊查询的使用 取值 需要 ${value} 取值
    -->
    <select id="findMonsterByName" parameterType="String" resultType="Monster">
        SELECT * FROM `monster` WHERE `name` LIKE '%${name}%'
    </select>
</mapper>


  1. 修改MonsterMapperTest.java ,完成测试
//演示多条件的查询
@Test
public void findMonsterByNameORId() {
    Monster monster = new Monster();
    monster.setId(5);
    monster.setName("白虎精");
    List<Monster> list = monsterMapper.findMonsterByNameORId(monster);
    for (Monster monster2 : list) {
      System.out.println(monster2);
    }
    if (sqlSession != null) {
      sqlSession.close();
    }
}
    //测试一个模糊查询
    @Test
    public void findMonsterByName() {
        List<Monster> list = monsterMapper.findMonsterByName("精");
        for (Monster monster : list) {
          System.out.println(monster);
        }
        if (sqlSession != null) {
          sqlSession.close();
        }
   }


传入HashMap(重点)


  1. HashMap 传入参数更加灵活,比如可以灵活的增加查询的属性,而不受限于Monster 这个Pojo 属性本身。
  2. 演示如何遍历一个List<Map<String,Object>> 的数据类型。


传入HashMap- 应用实例1


要求:声明一个方法,按传入参数是HashMap 的方式,查询id > 10 并且salary 大于40的所有妖怪。


  1. 修改MonsterMapper.java, 增加方法接口
//查询id > 10 并且salary 大于40, 要求传入的参数是HashMap
public List<Monster> findMonsterByIdAndSalary_PrameterHashMap(Map<String, Object> map);


  1. 修改MonsterMapper.xml
<!-- 实现findMonsterByIdAndSalary_PrameterHashMap -->
<select id="findMonsterByIdAndSalary_PrameterHashMap"  parameterType="map" resultType="Monster">
    SELECT * FROM monster
    WHERE id > #{id} AND salary > #{salary}
</select>


修改MonsterMapperTest.java 进行测试

 @Test
    public void findMonsterByIdAndSalary_PrameterHashMap() {
        //Diamond types are not supported at language level '5'
        //如何解决.=> 在pom.xml文件中指定编译器版本
        /*
             <!--指定Maven编译器 和 jdk版本-->
            <properties>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                <maven.compiler.source>1.8</maven.compiler.source>
                <maven.compiler.target>1.8</maven.compiler.target>
                <java.version>1.8</java.version>
            </properties>
         */
        Map<String, Object> map = new HashMap<>();
        map.put("id", 10);
        map.put("salary", 40);
        List<Monster> monsters =
                monsterMapper.findMonsterByIdAndSalary_PrameterHashMap(map);
        for (Monster monster : monsters) {
            System.out.println("monster--" + monster);
        }
        if (sqlSession != null) {
            sqlSession.close();
        }
        System.out.println("操作成功~");
    }


传入和返回HashMap- 应用实例


要求:将上面的方法的改成返回参数也以HashMap 的类型。


  1. 修改MonsterMapper.java
//查询id > 10 并且salary 大于40, 要求传入的参数是HashMap
public List<Map<String, Object>>
findMonsterByIdAndSalary_PrameterHashMap_ReturnHashMap(Map<String, Object> map);


  1. 修改MonsterMapper.xml
    <!--
    1. 配置/实现 public List<Map<String, Object>>
       findMonsterByIdAndSalary_PrameterHashMap_ReturnHashMap(Map<String, Object> map);
    2. id > 10 并且 salary 大于 40, 要求传入的参数和返回的是HashMap
    -->
    <select id="findMonsterByIdAndSalary_PrameterHashMap_ReturnHashMap" parameterType="map" resultType="map">
        SELECT * FROM `monster`  WHERE `id` > #{id} AND `salary` > #{salary}
    </select>


  1. 修改MonsterMapperTest.java
 @Test
    public void findMonsterByIdAndSalary_PrameterHashMap_ReturnHashMap() {
        Map<String, Object> map = new HashMap<>();
        map.put("id", 10);
        map.put("salary", 40);
        List<Map<String, Object>> monsterList =
                monsterMapper.findMonsterByIdAndSalary_PrameterHashMap_ReturnHashMap(map);
        //取出返回的结果-以map取出
        for (Map<String, Object> monsterMap : monsterList) {
            //System.out.println("monsterMap-" + monsterMap);
            //遍历monsterMap(方式1) ,取出属性和对应值
            //Set<String> keys = monsterMap.keySet();
            //for (String key : keys) {
            //    System.out.println(key + "=>" + monsterMap.get(key));
            //}
            //遍历monsterMap(方式2) ,取出属性和对应值
            for (Map.Entry<String, Object> entry : monsterMap.entrySet()) {
                System.out.println(entry.getKey() + "==>" + entry.getValue());
            }
            System.out.println("------------------------");
        }
        if (sqlSession != null) {
            sqlSession.close();
        }
        System.out.println("操作成功~");
    }


resultMap(结果集映射)


基本介绍


当实体类的属性和表的字段名字不一致时,我们可以通过resultMap 进行映射,从而屏蔽实体类属性名和表的字段名的不同.


案例演示


  1. 创建表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


  1. 创建User.java
public class User {
    private Integer user_id;
    private String username;
    private String useremail;
    public Integer getUser_id() {
        return user_id;
    }
    public void setUser_id(Integer user_id) {
        this.user_id = user_id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getUseremail() {
        return useremail;
    }
    public void setUseremail(String useremail) {
        this.useremail = useremail;
    }
    @Override
    public String toString() {
        return "User{" +
                "user_id=" + user_id +
                ", username='" + username + '\'' +
                ", useremail='" + useremail + '\'' +
                '}';
    }
}


  1. 创建com\nlc\mapper\UserMapper.java
public interface UserMapper {
    //添加方法
    public void addUser(User user);
    //查询所有的User
    public List<User> findAllUser();
}


  1. 修改resources\mybatis-config.xml, 改变别名的写法
<typeAliases>
<!-- 为某个 mapper指定一个别名, 下面可以在 XxxxxMapper.xml 做相应简化处理 --> 
 <!--<typeAlias type="com.nlc.entity.Monster" alias="Monster"/>-->
    <!--
             如果一个包下有很多的类,我们可以直接引入包,这样
            该包下面的所有类名,可以直接使用
     -->
   <package name="com.nlc.entity"/>
</typeAliases>


  1. 创建com\nlc\mapper\UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--解读
1. 这是一个mapper xml 文件
2. 该文件可以去实现对应的接口的方法
3. namespace 指定该xml文件和哪个接口对应!!!
-->
<mapper namespace="com.nlc.mapper.UserMapper">
    <!--
    1、配置方法public void addUser(User user);
    2、完成添加用户的任务, 注意这里user属性和表的字段名不一致
    -->
    <insert id="addUser" parameterType="User">
        INSERT INTO `user` (`user_email`,`user_name`)
        VALUE (#{useremail}, #{username})
    </insert>
    <!--
    1. 配置方法public List<User> findAllUser();
    2. 返回所有的user信息
    3. 按照传统的方式完成,会出现什么问题?=> 如果对象属性名和表字段相同时,就会设置值, 如果不同, 就会是默认值
    4. 我们可以使用resultMap来解决
    5. resultMap : 表示我们要定义一个resultMap
    6. id="findAllUserMap"  => id 就是程序员指定的resultMap id ,后面通过id可以使用他
    7. type="User" , 就是你需要返回的对象类型
    8. result column="user_email" property="useremail":  column="user_email" 表的字段名, property="useremail" 对象属性名
    9. resultMap="findAllUserMap" 表示使用我们定义的 resultMap , 通过id关联
    -->
    <resultMap id="findAllUserMap" type="User">
        <result column="user_email" property="useremail"/>
        <result column="user_name" property="username"/>
    </resultMap>
    <select id="findAllUser" resultMap="findAllUserMap">
        SELECT * FROM `user`
    </select>
    <!--使用表字段别名,来解决表的字段名和对象属性名,不一致问题, 可以用,但是我们仍然推荐使用resultmap-->
    <!--<select id="findAllUser" resultType="User">-->
    <!--    SELECT user_id ,user_name AS username,user_email AS useremail FROM `user`-->
    <!--</select>-->
</mapper>


  1. 创建src\test\java\com\nlc\mapper\UserMapperTest.java 完成测试
public class UserMapperTest {
    //属性
    private SqlSession sqlSession;
    private UserMapper userMapper;
    //初始化
    @Before
    public void init() {
        sqlSession = MyBatisUtils.getSqlSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
    }
    @Test
    public void addUser() {
        User user = new User();
        user.setUsername("jack");
        user.setUseremail("jack@qq.com");
        userMapper.addUser(user);
        //如果是增删改, 需要commit()
        if(sqlSession != null) {
            sqlSession.commit();
            sqlSession.close();
        }
        System.out.println("操作OK~");
    }
    @Test
    public void findAllUser() {
        List<User> users = userMapper.findAllUser();
        for (User user : users) {
            System.out.println("user--" + user);
        }
        if(sqlSession != null) {
            sqlSession.close();
        }
        System.out.println("操作OK~");
    }
}


注意事项和细节


  1. 解决表字段和对象属性名不一致, 也支持使用字段别名

实现findAllUser【使用别名屏蔽属性名和字段名不一致,可以用,但是复用性不好】

<!-- <select id="findAllUser" resultType="User">
SELECT user_id,user_name AS username, user_email AS useremail FROM user
</select> -->
  1. 如果是MyBatis-Plus 处理就比较简单, 可以使用注解@TableField 来解决。
    实体字段名和表字段名不一致的问题,还可以使用@TableName 来解决实体类名和表名不一致的问题。
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
XML 前端开发 Java
讲解SSM的xml文件
本文详细介绍了SSM框架中的xml配置文件,包括springMVC.xml和applicationContext.xml,涉及组件扫描、数据源配置、事务管理、MyBatis集成以及Spring MVC的视图解析器配置。
57 1
|
2月前
|
SQL 存储 API
Flink实践:通过Flink SQL进行SFTP文件的读写操作
虽然 Apache Flink 与 SFTP 之间的直接交互存在一定的限制,但通过一些创造性的方法和技术,我们仍然可以有效地实现对 SFTP 文件的读写操作。这既展现了 Flink 在处理复杂数据场景中的强大能力,也体现了软件工程中常见的问题解决思路——即通过现有工具和一定的间接方法来克服技术障碍。通过这种方式,Flink SQL 成为了处理各种数据源,包括 SFTP 文件,在内的强大工具。
165 15
|
1月前
|
SQL 关系型数据库 MySQL
数据库导入SQL文件:全面解析与操作指南
在数据库管理中,将SQL文件导入数据库是一个常见且重要的操作。无论是迁移数据、恢复备份,还是测试和开发环境搭建,掌握如何正确导入SQL文件都至关重要。本文将详细介绍数据库导入SQL文件的全过程,包括准备工作、操作步骤以及常见问题解决方案,旨在为数据库管理员和开发者提供全面的操作指南。一、准备工作在导
235 0
|
3月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
13天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
9天前
|
Java Maven
maven项目的pom.xml文件常用标签使用介绍
第四届人文,智慧教育与服务管理国际学术会议(HWESM 2025) 2025 4th International Conference on Humanities, Wisdom Education and Service Management
58 8
|
1月前
|
SQL 数据库
DBeaver执行sql文件
本文介绍了DBeaver这款支持多种数据库的通用数据库管理工具和SQL客户端,它具备查看数据库结构、执行SQL查询和脚本、浏览和导出数据等功能。
84 1
DBeaver执行sql文件
|
1月前
|
SQL 关系型数据库 MySQL
|
1月前
|
SQL 数据库
为什么 SQL 日志文件很大,我应该如何处理?
为什么 SQL 日志文件很大,我应该如何处理?
|
1月前
|
SQL 存储 关系型数据库
SQL文件导入MySQL数据库的详细指南
数据库中的数据转移是一项常规任务,无论是在数据迁移过程中,还是在数据备份、还原场景中,导入导出SQL文件显得尤为重要。特别是在使用MySQL数据库时,如何将SQL文件导入数据库是一项基本技能。本文将详细介绍如何将SQL文件导入MySQL数据库,并提供一个清晰、完整的步骤指南。这篇文章的内容字数大约在
136 1