带你了解什么是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

  1. 在原来的项目中,新建xml-mapper 项目演示xml 映射器的使用。
  2. 新建Module 后,先创建需要的包,再将需要的文件/资源拷贝过来(这里我们拷贝Monster.java、resources/jdbc.properties 和mybatis-config.xml)。
  3. 创建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 主键[前面使用过了]

parameterType(输入参数类型)

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

案例1:请查询id = 1 或者name = ‘白骨精’ 的妖怪
案例2:请查询name 中包含"牛魔王" 的妖怪

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

    //通过id 或者名字查询
    public List<Monster> findMonsterByNameORId(Monster monster);
    //查询名字中含义'精'妖怪
    public List<Monster> findMonsterByName(String name);
    
  2. 修改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>
  1. 修改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> -->
    
  2. 如果是MyBatis-Plus 处理就比较简单, 可以使用注解@TableField 来解决。
    实体字段名和表字段名不一致的问题,还可以使用@TableName 来解决实体类名和表名不一致的问题。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨犀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值