6. Mybatis映射文件深入

阅读: 评论:0

6. Mybatis映射文件深入

6. Mybatis映射文件深入

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);

② l

image-20210315105752540
<!--方案一: 这表的主键必须是自增长的 auto_incrementuseGeneratedKeys="true" 让自增长的主键开启返回功能keyColumn="id"  user表中主键列keyProperty="id" user实体主键属性注意:支持主键自增类型的数据库 MySQL 和 SqlServer , oracle不支持
-->
<insert id="addUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id">insert into user values(null,#{user.username},#{user.birthday},#{user.sex},#{user.address})
</insert>

③ 测试

image-20210315110218995
    // 测试插入数据, 返回主键ID@Testpublic void test11() throws Exception {// 1. 获取 sqlSession 数据库连接会话MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = SqlSession();//2. 会话对象得到UserMapper接口的代理对象UserMapper userMapper = Mapper(UserMapper.class);//3. 执行插入一个user对象, 返回主键ID//创建user对象User user = new User();//设置usernameuser.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.Datejava.sql.Date date1 = new java.sql.Time());
//        System.out.println(date1);// 设置user的生日user.setBirthday(date1);//设置 sexuser.setSex("男");//设置 addressuser.setAddress("湖南嚼槟榔的那嘎达地方");//调用插入数据的方法int i = userMapper.addUser(user);System.out.println("插入数据的行数: " + i);//查询插入后返回的主键IDSystem.out.println("插入数据的主键ID: " + Id());//7. 关闭会话myBatisUtilmitAndClose(sqlSession);}

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

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

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

image-20210315125223706
-- 查询数据的同时,查询返回自增的ID
-- 注意:这两行SQL要按照顺序同时执行,否则单独查询 SELECT LAST_INSERT_ID(); 不会返回最新的自增ID
insert 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 参数注解,直接写 #{属性名} 即可
}   

② l

image-20210315125852891
<!--方案二: <selectKey>keyColumn="id" user表中主键列keyProperty="id" user实体主键属性resultType="int" user实体主键属性类型order="AFTER"  表示此标签内部sql语句在insert执行之前(执行),还是之后执行(执行)AFTER 之后执行【在自增主键时】BEFORE 之前执行【使用指定主键时】
-->
<insert id="addUser"><selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">SELECT LAST_INSERT_ID()</selectKey>insert into user values(null, #{username},#{birthday},#{sex},#{address})
</insert>

③ 测试

image-20210315125959784
    // 测试插入数据, 返回主键ID@Testpublic void test11() throws Exception {// 1. 获取 sqlSession 数据库连接会话MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = SqlSession();//2. 会话对象得到UserMapper接口的代理对象UserMapper userMapper = Mapper(UserMapper.class);//3. 执行插入一个user对象, 返回主键ID//创建user对象User user = new User();//设置usernameuser.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.Datejava.sql.Date date1 = new java.sql.Time());
//        System.out.println(date1);// 设置user的生日user.setBirthday(date1);//设置 sexuser.setSex("男");//设置 addressuser.setAddress("湖南嚼槟榔的那嘎达地方");//调用插入数据的方法int i = userMapper.addUser(user);System.out.println("插入数据的行数: " + i);//查询插入后返回的主键IDSystem.out.println("插入数据的主键ID: " + Id());//7. 关闭会话myBatisUtilmitAndClose(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}-- 如果只有id
select * 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<U>* */List<User> findUsersByIdAndUserNameIf(@Param("id") String id, @Param("username") String username);
}

② l

image-20210315161407282
    <!--java 逻辑:username = null;  都没有意义username = "";if(username != null && !username.equals("")){and username = ?}sql逻辑:if标签: 必要属性test (写判断条件)满足条件,拼接sqlwhere标签: 根据最终的条件,动态修改成合适的语法--><select id="findUsersByIdAndUserNameIf" resultType="user">select * from user<where><if test="id != null and id != ''">id = #{id}</if><if test="username != null and username != ''">and username = #{username}</if></where></select>

③ 测试

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

② l

image-20210315172300336
    <!--set标签: 用在update语句中,动态修改sql语法--><update id="updateUserById">update user<set><if test="username != null and username != ''">username = #{username},</if><if test="birthday != null and birthday != ''">birthday = #{birthday},</if><if test="sex != null and sex != ''">sex = #{sex},</if><if test="address != null and address != ''">address = #{address}</if></set>where id = #{id}</update>

③ 测试

image-20210315192700694
// 测试根据 id 修改用户信息
@Test
public void test13() throws Exception {// 1. 获取 sqlSession 数据库连接会话MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = SqlSession();//2. 会话对象得到UserMapper接口的代理对象UserMapper userMapper = Mapper(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. 关闭会话myBatisUtilmitAndClose(sqlSession);
}

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

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

需求

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

select * from user where id in (41,43,46);
* <foreach>标签用于遍历集合,它的属性:• collection:代表要遍历的集合元素• open:代表语句的开始部分• close:代表结束部分• item:代表遍历集合的每个元素,生成的变量名• sperator:代表分隔符

练习二个版本

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

  2. 普通array数组 作为 查询条件参数的容器

① UserMapper

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

② l

image-20210315193300734
<!--foreach 标签(遍历)1. collection属性: 被遍历的容器类型list/array2. item : 被遍历出来的元素3. open: 遍历开始时的内容4. close: 遍历结束的内容5. separator : 每遍历一次就添加一次的分隔符(最后一次遍历不加)距离: list = {1,2,3}遍历: (1,2,3)
-->
<select id="findUsersByIds" resultType="user">select * from user where id in<foreach collection="list" item="id" open="(" close=")" separator=",">#{id}</foreach>
</select><select id="findUsersByIds2" resultType="user">select * from user where id in<foreach collection="array" item="id" open="(" close=")" separator=",">#{id}</foreach>
</select>

③ 测试

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

2.3 SQL片段

应用场景

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

应用案例

①  寻找重复的 sql

image-20210315193930864

② l

image-20210315194113121
    <select id="findUsersByIds" resultType="user">
--         select * from user<include refid="selectUser"/>where id in<foreach collection="list" item="id" open="(" close=")" separator=",">#{id}</foreach></select><select id="findUsersByIds2" resultType="user">
--         select * from user<include refid="selectUser"/>where id in<foreach collection="array" item="id" open="(" close=")" separator=",">#{id}</foreach></select><!--sql片段: 抽取重复出现的sql语句在其他的语句中可以include标签进行引用--><sql id="selectUser">select * from user</sql>

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

2.4 知识小结

MyBatis映射文件配置

<select>:查询<insert>:插入<update>:修改<delete>:删除<selectKey>:插入返回主键<where>:where条件<if>:if判断<foreach>:for循环<set>:set设置<sql>:sql片段抽取

本文发布于:2024-01-28 06:12:29,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17063935625376.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:文件   Mybatis
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23