6. Mybatis映射文件深入 - 新增数据后返回主键ID - 动态SQL - SQL片段

网友投稿 762 2022-11-21

6. Mybatis映射文件深入 - 新增数据后返回主键ID - 动态SQL - SQL片段

6. Mybatis映射文件深入 - 新增数据后返回主键ID - 动态SQL - SQL片段

6. Mybatis映射文件深入 - 新增数据后返回主键ID - 动态SQL - SQL片段

前言

在前面的篇章中,我们已经认识了如何使用 resultMap标签 映射查询的结果集字段、多条件查询、模糊查询。

下面我们继续来深入认识一下 MyBatis 的映射文件。

新增数据后,返回主键 ID

应用场景

数据库保存一个user对象后, 然后在控制台打印此新增user的主键值(id)

# 点外卖 1. 点一份饭 -> 产生一个订单, 美团会往订单表插入一条数据(主键) 2. 需要返回这条记录的主键, 然后给第三方配送平台, 送外卖

实现案例一:基于MyBatis 框架自带的主键返回功能

① UserMapper接口

image-20210315105713661

/* * # 复杂操作:插入一条数据返回对应的主键 * sql: * insert into user values(null,?,?,?,?); * 参数: user(username,birthday,sex,address) * 返回值: int(其实是被影响的行数) * void * * 对应的主键: user.id * */int addUser(@Param("user") User user);

② UserMapper.xml

image-20210315105752540

insert into user values(null,#{user.username},#{user.birthday},#{user.sex},#{user.address})

③ 测试

image-20210315110218995

// 测试插入数据, 返回主键ID @Test public void test11() throws Exception { // 1. 获取 sqlSession 数据库连接会话 MyBatisUtil myBatisUtil = new MyBatisUtil(); SqlSession sqlSession = myBatisUtil.getSqlSession(); //2. 会话对象得到UserMapper接口的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //3. 执行插入一个user对象, 返回主键ID //创建user对象 User user = new User(); //设置username user.setUsername("李云龙"); //设置字符串的日期 String str = "2021-03-15"; // 使用SimpleDateFormat将其解析为 Date 对象 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); java.util.Date date = simpleDateFormat.parse(str); // 再将date设置为 java.sql.Date java.sql.Date date1 = new java.sql.Date(date.getTime());// System.out.println(date1); // 设置user的生日 user.setBirthday(date1); //设置 sex user.setSex("男"); //设置 address user.setAddress("湖南嚼槟榔的那嘎达地方"); //调用插入数据的方法 int i = userMapper.addUser(user); System.out.println("插入数据的行数: " + i); //查询插入后返回的主键ID System.out.println("插入数据的主键ID: " + user.getId()); //7. 关闭会话 myBatisUtil.commitAndClose(sqlSession); }

实现案例二:基于SQL的 SELECT LAST_INSERT_ID() 语句

上面的案例一是采用MyBatis框架自动的主键返回功能,而有些时候,我们的主键有可能不是自增 ID,有可能是自己生成的 UUID。

这时候就需要采用一些 SQL 语句进行查询了。下面我们来模拟查询,如下:

image-20210315125223706

-- 查询数据的同时,查询返回自增的ID-- 注意:这两行SQL要按照顺序同时执行,否则单独查询 SELECT LAST_INSERT_ID(); 不会返回最新的自增IDinsert into user values(null, "张飞", "2021-03-15", "男", "三国"); -- 插入数据SELECT LAST_INSERT_ID(); -- 查询最新的自增ID

在这里我们在插入数据之后,同时执行了查询最新自增ID的操作,从而获取自增的ID。

下面我们在代码来实现一下这个效果。

① UserMapper接口

image-20210315110410329

public interface UserMapper { /* * # 复杂操作:插入一条数据返回对应的主键 * sql: * insert into user values(null,?,?,?,?); * 参数: user(username,birthday,sex,address) * 返回值: int(其实是被影响的行数) * void * * 对应的主键: user.id * */ //int addUser(@Param("user") User user); // 设置 @Param 参数注解后,在映射xml文件必须写 #{user.属性名} int addUser(User user); // 没有设置 @Param 参数注解,直接写 #{属性名} 即可}

② UserMapper.xml

image-20210315125852891

SELECT LAST_INSERT_ID() insert into user values(null, #{username},#{birthday},#{sex},#{address})

③ 测试

image-20210315125959784

// 测试插入数据, 返回主键ID @Test public void test11() throws Exception { // 1. 获取 sqlSession 数据库连接会话 MyBatisUtil myBatisUtil = new MyBatisUtil(); SqlSession sqlSession = myBatisUtil.getSqlSession(); //2. 会话对象得到UserMapper接口的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //3. 执行插入一个user对象, 返回主键ID //创建user对象 User user = new User(); //设置username user.setUsername("李云龙"); //设置字符串的日期 String str = "2021-03-15"; // 使用SimpleDateFormat将其解析为 Date 对象 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); java.util.Date date = simpleDateFormat.parse(str); // 再将date设置为 java.sql.Date java.sql.Date date1 = new java.sql.Date(date.getTime());// System.out.println(date1); // 设置user的生日 user.setBirthday(date1); //设置 sex user.setSex("男"); //设置 address user.setAddress("湖南嚼槟榔的那嘎达地方"); //调用插入数据的方法 int i = userMapper.addUser(user); System.out.println("插入数据的行数: " + i); //查询插入后返回的主键ID System.out.println("插入数据的主键ID: " + user.getId()); //7. 关闭会话 myBatisUtil.commitAndClose(sqlSession); }

2.2 动态SQL

2.2.1 什么是动态SQL

动态SQL就是基于不同的查询情况,动态改变不同的查询条件,组合查询出来的结果。

下面我们使用一个超简单的查询需求来说明什么是动态SQL。

需求

1589022259909

基于【编号】和 【用户名】来搜索用户,而【编号】和【用户名】都可能为空。

实现方式

把id和username封装到user对象中,将user对象中不为空的属性作为查询条件。

这个时候我们执行的sql就有多种可能。

-- 如果id和用户名不为空select * from user where id= #{id} and username = #{username}-- 如果只有idselect * from user where id= #{id} -- 如果只有用户名select * from user where username = #{username}-- 如果id和用户名都为空select * from user

像上面这样, 根据传入的参数不同, 需要执行的SQL的结构就会不同,这就是动态SQL

而对于在映射配置文件中动态设置SQL的话,我们就需要熟悉一下相关判断的标签文件。

2.2.2 if 条件判断

需求

把id和username封装到user对象中,将user对象中不为空的属性作为查询条件

① UserMapper接口

image-20210315152119968

public interface UserMapper { /* * # 动态sql * 需求: 查询符合一定条件的用户(条件是可选的) * select * from user * where * id = ? -- 可能有 * and username = ? -- 可能有 * * 参数: int id, String username * 返回值: List * */ List findUsersByIdAndUserNameIf(@Param("id") String id, @Param("username") String username);}

② UserMapper.xml

image-20210315161407282

③ 测试

image-20210315162703515

// 测试根据 id 以及 username 查询用户@Testpublic void test12() throws Exception { // 1. 获取 sqlSession 数据库连接会话 MyBatisUtil myBatisUtil = new MyBatisUtil(); SqlSession sqlSession = myBatisUtil.getSqlSession(); //2. 会话对象得到UserMapper接口的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //3. 执行根据 id 以及 username 查询用户 //3.1 同时查询 id 、username List users = userMapper.findUsersByIdAndUserNameIf("20", "李云龙"); for (User user : users) { System.out.println("3.1 同时查询 id 、username: " + user); } //3.2 单独查询 id List users2 = userMapper.findUsersByIdAndUserNameIf("19", ""); for (User user : users2) { System.out.println("3.2 单独查询 id: " + user); } //3.3 单独查询 username List users3 = userMapper.findUsersByIdAndUserNameIf("", "豹子精"); for (User user : users3) { System.out.println("3.2 单独查询 username: " + user); } //7. 关闭会话 myBatisUtil.commitAndClose(sqlSession);}

2.2.3 set 用于update语句

需求

动态更新user表数据,如果该属性有值就更新,没有值不做处理

① UserMapper接口

image-20210315172059455

/* * # 动态sql * 需求: 修改某个用户信息 * update user * set username = ?, -- 动态 * birthday = ?, -- 动态 * sex = ?, -- 动态 * address = ? -- 动态 * where id = ?; * 参数: User * 返回值: void * * */ int updateUserById(User user);

② UserMapper.xml

image-20210315172300336

update user username = #{username}, birthday = #{birthday}, sex = #{sex}, address = #{address} where id = #{id}

③ 测试

image-20210315192700694

// 测试根据 id 修改用户信息@Testpublic void test13() throws Exception { // 1. 获取 sqlSession 数据库连接会话 MyBatisUtil myBatisUtil = new MyBatisUtil(); SqlSession sqlSession = myBatisUtil.getSqlSession(); //2. 会话对象得到UserMapper接口的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //3. 更具ID修改用户信息 User user = new User(); user.setUsername("小王"); user.setSex("女"); user.setId(20); // 修改ID为20的用户 //update user SET username = ?, sex = ? where id = ? userMapper.updateUserById(user); //7. 关闭会话 myBatisUtil.commitAndClose(sqlSession);}

2.2.4 foreach 用于循环遍历【重点】

“ 当如果查询条件是 in (....) 之类的需要遍历查询条件的情况,此时就需要使用 foreach 标签来处理了。 ”

需求

根据多个id查询,user对象的集合

select * from user where id in (41,43,46);

* 标签用于遍历集合,它的属性: • collection:代表要遍历的集合元素 • open:代表语句的开始部分 • close:代表结束部分 • item:代表遍历集合的每个元素,生成的变量名 • sperator:代表分隔符

练习二个版本

普通list集合 作为 查询条件参数的容器普通array数组 作为 查询条件参数的容器

① UserMapper

image-20210315193152470

/* * # 动态sql3 * 需求: 查询某几个用户信息 * select * from user where id in * (1,3,4) -> 动态的 * * 参数: List list / int[] array * 返回值: List * */ List findUsersByIds(List list); // 普通list集合 作为 查询条件参数的容器 List findUsersByIds2(int[] array); // 普通array数组 作为 查询条件参数的容器

② UserMapper.xml

image-20210315193300734

③ 测试

image-20210315193639272

// 测试 in 条件的查询@Testpublic void test14() throws Exception { // 1. 获取 sqlSession 数据库连接会话 MyBatisUtil myBatisUtil = new MyBatisUtil(); SqlSession sqlSession = myBatisUtil.getSqlSession(); //2. 会话对象得到UserMapper接口的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 以集合保存 in 条件参数 List list = new ArrayList<>(); Collections.addAll(list,1,3,4); List result = userMapper.findUsersByIds(list); System.out.println("以集合保存 in 条件参数: " + result); // 以数组保存 in 条件参数 int[] array = {2,4,6}; List result2 = userMapper.findUsersByIds2(array); System.out.println("以数组保存 in 条件参数: " + result2); //7. 关闭会话 myBatisUtil.commitAndClose(sqlSession);}

2.3 SQL片段

应用场景

映射文件中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。

应用案例

①  寻找重复的 sql

image-20210315193930864

② UserMapper.xml

image-20210315194113121

select * from user

设置之后,再使用上面 foreach 标签的测试代码执行一下验证是否正常执行即可。

2.4 知识小结

MyBatis映射文件配置

暂时没有评论,来抢沙发吧~