【测试开发】知识点-mybatis,XML 映射文件介绍

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 【测试开发】知识点-mybatis,XML 映射文件介绍

MyBatis 的真正强大在于它的语句映射,它指导着 Mybatis 如何进行数据库的增删改查。在之前的demo当中已简单使用过,写sql的那个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">
<mapper namespace="com.pingguo.bloomtest.dao.UserMapper">
    <select id="getUserById" resultType="com.pingguo.bloomtest.pojo.User" databaseId="mysql">
      select * from user where id = #{id}
    </select>
</mapper>


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


  • cache – 该命名空间的缓存配置。
  • cache-ref – 引用其它命名空间的缓存配置。
  • resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
  • parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
  • sql – 可被其它语句引用的可重用语句块。
  • insert – 映射插入语句。
  • update – 映射更新语句。
  • delete – 映射删除语句。
  • select – 映射查询语句。


不过,先来看下增删改查。


一、增删改查速览


我继续在接口里新增几个方法(查询已有):


public interface UserMapper {
    // 查询
    User getUserById(Integer id);
    // 新增
    void addUser(User user);
    // 修改
    void updateUser(User user);
    // 删除
    void deleteUser(Long id);
}


在映射文件UserMapper.xml中,使用insertupdatedelete标签来写对应方法的sql:


<!--新增-->
<insert id="addUser">
    insert into user(username, password, createTime, updateTime)
    values(#{username}, #{password}, #{createTime}, #{updateTime})
</insert>
<!--更新-->
<update id="updateUser">
    update user
      set username=#{username}, password=#{password}, createTime=#{createTime}, updateTime=#{updateTime}
      where id=#{id}
</update>
<!--删除-->
<delete id="deleteUser">
    delete from user where id=#{id}
</delete>


另外,mybatis 允许增删改直接定义如下的返回值:Integer、Long、Boolean。那么接口里定义的方法就可以写成这样:


public interface UserMapper {
    // 查询
    User getUserById(Integer id);
    // 新增
    boolean addUser(User user);
    // 修改
    boolean updateUser(User user);
    // 删除
    boolean deleteUser(Long id);
}


addUser方法来说,新增成功之后返回的就是true


在测试类里可以测试下上面几个方法,这里贴出来测试一下新增:


@Test
void test3() throws IOException{
    SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    // 获取到的 SqlSession 不会自动提交数据
    SqlSession session = sqlSessionFactory.openSession();
    User newUser = new User();
    newUser.setUsername("新用户1");
    newUser.setPassword("111111");
    newUser.setCreateTime(new Date());
    newUser.setUpdateTime(new Date());
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);
        userMapper.addUser(newUser);
        // 需要这里手动提交
        session.commit();
    } finally {
        session.close();
    }
}


注意这里sqlSessionFactory.openSession()不会自动提交数据,需要session.commit()手动提交。如果需要自动提交,里面传入true即可:


sqlSessionFactory.openSession(true)


e7f4a5b579ac4fd88d32113befce3709_tplv-k3u1fbpfcp-watermark.png


新增成功。


f43009e15c0646aaaa1fea7418a01ff8_tplv-k3u1fbpfcp-watermark.png


其他几个也成功通过测试。


二、insert获取自增主键的值


mysql 的自增主键,mybatis 也可以获取到,只需要添加一个属性useGeneratedKeys,默认是false


那获取到的主键值,可以通过keyProperty将这个值封装给 Javabean 的某个属性,比如User类中的id


<!--新增-->
<insert id="addUser" useGeneratedKeys="true" keyProperty="id">
    insert into user(username, password, createTime, updateTime)
    values(#{username}, #{password}, #{createTime}, #{updateTime})
</insert>


可以在之前的测试方法里加一个打印,看下获取到的主键值:


成功获取到主键值为 12 。


查看数据库表里新增多数据主键就是 12 。


42dbee2767a34d69849f00fb7f56073a_tplv-k3u1fbpfcp-watermark.png


三、单个参数、多个参数、对象


1. 单个参数


拿上面根据 id 进行查询为例:


<select id="getUserById" resultType="com.pingguo.bloomtest.pojo.User" databaseId="mysql">
  select * from user where id = #{id}
</select>


使用#{参数名},mybatis就会正确取出参数值。


当只有一个参数的时候,mybatis 不会做特殊处理,比如sql中的where条件是根据id来查询,但我就算写#{abc},也正常查询。


2. 多个参数


在接口UserMapper里再定义一个新的方法,里面传入多个参数:


// 查询 使用多个参数
User getUserByIdAndUsername(Integer id, String username);


对应的增加sql映射:


<select id="getUserByIdAndUsername" resultType="com.pingguo.bloomtest.pojo.User" databaseId="mysql">
  select * from user where id = #{id} and username=#{username}
</select>


测试一下,可以正常查询。


@Test
void test2params() throws IOException {
    SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    SqlSession session = sqlSessionFactory.openSession();
    UserMapper userMapper = session.getMapper(UserMapper.class);
    System.out.println(userMapper.getUserByIdAndUsername(3, "大周"));
}


3. 对象


如果多个参数正好是我们业务逻辑的数据模型,那可以直接传入对象,比如POJO,通过#{属性名}取出属性值。


如果多个参数没有对应的POJO,为了方便,也可以传入 Map 。


在 UserMapper 里增加方法:


User getUserByMap(Map<String, Object> map);


sql 映射文件增加对应配置:


<select id="getUserByMap" resultType="com.pingguo.bloomtest.pojo.User" databaseId="mysql">
      select * from user where id = #{id} and username=#{username}
    </select>


新增个测试方法,查询正常。


@Test
    void testByMap() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession session = sqlSessionFactory.openSession();
        UserMapper userMapper = session.getMapper(UserMapper.class);
        Map<String, Object> map = new HashMap<>();
        map.put("id", 3);
        map.put("username", "大周");
        System.out.println(userMapper.getUserByMap(map));
    }


如果上述这种 map 还要经常使用,推荐编写一个TO(Transfer Object)数据传输对象。


四、$ 和 # 取值


mybatis 中是采用#{}${}都是可以取值的,但是两者还是有区别的,比如:


<select id="getUserByIdAndUsername" resultType="com.pingguo.bloomtest.pojo.User" databaseId="mysql">
      select * from user where id = ${id} and username=#{username}
    </select>


我在这里把2个参数分别用了不同的方法来取值:${id}#{username},然后执行之前的测试函数,看下打印结果。


1268169-20211208224355355-1983841431.png


区别就是:


  • #{},是以预编译形式,讲参数设置到 sql 语句中
  • ${},取出的值直接拼装在 sql 语句中,会存在一定的安全问题

大多数情况下,我们都去使用#{}


不过在某些情况下,还是会用到${}。比如一个工资表按照年份进行了拆分,表名前面是年份,那么要动态查询表的时候,年份就是个变量。


表名是不能预编译的,所以不能使用#{}。对于这种原生JDBC不支持占位符的地方,就可以使用${}


select * from ${year}_salary where xxx;


再比如,用到排序,我想把排序的条件和升序降序可以动态的穿进来,也可以使用${}


select * user order by ${age} ${desc_order};


五、select 元素


1. select 返回 list


如果我定义了一个查询,返回的是一个 list。


List<User> getUserByUsernameLike(String username);


sql 映射文件这样写:


<select id="getUserByLastNameLike" resultType="com.pingguo.bloomtest.pojo.User" databaseId="mysql">
      select * from user where username like #{username}
    </select>


注意这里如果返回的是一个集合类型,resultType里要写集合中的类型。


2. select 返回 map


如果需要返回一条记录的 map,key 就是列名,value 就是对应的值。


Map<String, Object> getUserByIdReturnMap(Integer id);


sql 映射文件这样写:


<select id="getUserByIdReturnMap" resultType="map">
        select * from user where id = #{id}
    </select>


测试下,查询正常。


1268169-20211209215512422-315846343.png


如果需要封装多条记录比如Map<Integer, User>,key 是记录的主键,value 是记录封装后的 javabean 。


Map<Integer, User> getUserByUsernameReturnMap(String username);


sql 映射文件:


<select id="getUserByUsernameReturnMap" resultType="com.pingguo.bloomtest.pojo.User">
        select * from user where username like #{username}
    </select>


这里的返回类型还是 User,现在 value 有了,那么如何把主键作为 map 的 key 呢?

使用注解@MapKey("id"),告诉 mybatis 使用哪个属性作为 key:


@MapKey("id")
    Map<Integer, User> getUserByUsernameReturnMap(String username);


测试一下:


1268169-20211209220643633-663265920.png


如果换成其他属性作为 key 也是可以的。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
3月前
|
SQL Java 数据库连接
MyBatis 的映射关系
MyBatis 核心功能之一是映射关系,支持一对一、一对多和多对多三种 ORM 映射。通过实体类与配置文件结合,开发者可灵活实现数据关联,提升数据库操作效率。
293 4
|
9月前
|
SQL Java 数据库连接
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
|
9月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
517 0
|
7月前
|
SQL XML Java
菜鸟之路Day35一一Mybatis之XML映射与动态SQL
本文介绍了MyBatis框架中XML映射与动态SQL的使用方法,作者通过实例详细解析了XML映射文件的配置规范,包括namespace、id和resultType的设置。文章还对比了注解与XML映射的优缺点,强调复杂SQL更适合XML方式。在动态SQL部分,重点讲解了`&lt;if&gt;`、`&lt;where&gt;`、`&lt;set&gt;`、`&lt;foreach&gt;`等标签的应用场景,如条件查询、动态更新和批量删除,并通过代码示例展示了其灵活性与实用性。最后,通过`&lt;sql&gt;`和`&lt;include&gt;`实现代码复用,优化维护效率。
709 5
|
9月前
|
XML Java 数据库连接
二、搭建MyBatis采用xml方式,验证CRUD(增删改查操作)
二、搭建MyBatis采用xml方式,验证CRUD(增删改查操作)
329 21
|
9月前
|
SQL Java 数据库连接
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
|
9月前
|
SQL XML Java
七、MyBatis自定义映射resultMap
七、MyBatis自定义映射resultMap
279 6
|
9月前
|
Java 数据库连接 mybatis
MyBatis篇-映射关系(1-1 1-n n-n)
本文介绍了MyBatis中四种常见关系映射的配置方法,包括一对一、一对多、多对一和多对多。**一对一**通过`resultMap`实现属性与字段的映射;**一对多**以用户-角色为例,使用`&lt;collection&gt;`标签关联集合数据;**多对一**以作者-博客为例,利用`&lt;association&gt;`实现关联;**多对多**则通过引入第三方类(如UserForDept)分别在User和Dept类中添加集合属性,并配置对应的`&lt;collection&gt;`标签完成映射。这些方法解决了复杂数据关系的处理问题,提升了开发效率。
|
XML Java 数据库连接
Mybatis映射关系
简介:本文介绍了MyBatis框架中四种常见的关系映射方式,包括一对一、一对多、多对一及多对多。一对一通过简单属性映射实现;一对多通过在主对象中添加集合属性并使用`&lt;collection&gt;`标签映射子对象集合;多对一则利用`&lt;association&gt;`标签在主对象中映射单个子对象;多对多需引入第三方类,分别在两个主对象中添加对方的集合属性,并通过`&lt;collection&gt;`标签实现映射。
239 32
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件