在前面的篇章中,我们已经认识了如何使用 resultMap标签 映射查询的结果集字段、多条件查询、模糊查询。
下面我们继续来深入认识一下 MyBatis 的映射文件。
向数据库保存一个user对象后, 然后在控制台打印此新增user的主键值(id)
# 点外卖1. 点一份饭 -> 产生一个订单, 美团会往订单表插入一条数据(主键)2. 需要返回这条记录的主键, 然后给第三方配送平台, 送外卖
① UserMapper接口
/** # 复杂操作:插入一条数据返回对应的主键* sql:* insert into user values(null,?,?,?,?);* 参数: user(username,birthday,sex,address)* 返回值: int(其实是被影响的行数)* void** 对应的主键: user.id* */
int addUser(@Param("user") User user);
② l
<!--方案一: 这表的主键必须是自增长的 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>
③ 测试
// 测试插入数据, 返回主键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);}
上面的案例一是采用MyBatis框架自动的主键返回功能,而有些时候,我们的主键有可能不是自增 ID,有可能是自己生成的 UUID。
这时候就需要采用一些 SQL 语句进行查询了。下面我们来模拟查询,如下:
-- 查询数据的同时,查询返回自增的ID
-- 注意:这两行SQL要按照顺序同时执行,否则单独查询 SELECT LAST_INSERT_ID(); 不会返回最新的自增ID
insert into user values(null, "张飞", "2021-03-15", "男", "三国"); -- 插入数据
SELECT LAST_INSERT_ID(); -- 查询最新的自增ID
在这里我们在插入数据之后,同时执行了查询最新自增ID的操作,从而获取自增的ID。
下面我们在代码来实现一下这个效果。
① UserMapper接口
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
<!--方案二: <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>
③ 测试
// 测试插入数据, 返回主键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就是基于不同的查询情况,动态改变不同的查询条件,组合查询出来的结果。
下面我们使用一个超简单的查询需求来说明什么是动态SQL。
需求
基于【编号】和 【用户名】来搜索用户,而【编号】和【用户名】都可能为空。
实现方式
把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的话,我们就需要熟悉一下相关判断的标签文件。
需求
把id和username封装到user对象中,将user对象中不为空的属性作为查询条件
① UserMapper接口
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
<!--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>
③ 测试
// 测试根据 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);
}
需求
动态更新user表数据,如果该属性有值就更新,没有值不做处理
① UserMapper接口
/** # 动态sql* 需求: 修改某个用户信息* update user* set username = ?, -- 动态* birthday = ?, -- 动态* sex = ?, -- 动态* address = ? -- 动态* where id = ?;* 参数: User* 返回值: void** */int updateUserById(User user);
② l
<!--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>
③ 测试
// 测试根据 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);
}
“当如果查询条件是 in (....) 之类的需要遍历查询条件的情况,此时就需要使用 foreach 标签来处理了。
”
需求
根据多个id查询,user对象的集合
select * from user where id in (41,43,46);
* <foreach>标签用于遍历集合,它的属性:• collection:代表要遍历的集合元素• open:代表语句的开始部分• close:代表结束部分• item:代表遍历集合的每个元素,生成的变量名• sperator:代表分隔符
练习二个版本
普通list集合 作为 查询条件参数的容器
普通array数组 作为 查询条件参数的容器
① UserMapper
/** # 动态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
<!--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>
③ 测试
// 测试 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);
}
映射文件中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。
① 寻找重复的 sql
② l
<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 标签的测试代码执行一下验证是否正常执行即可。
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小时内删除。
留言与评论(共有 0 条评论) |