MyBatis之动态SQL
Posted 一宿君
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis之动态SQL相关的知识,希望对你有一定的参考价值。
学习目标
- 列举出实现动态SQL的主要元素有哪些?
- trim元素的主要功能是什么?
- set元素主要用在什么操作上?
- 有in语句查询的时候需要使用哪个元素?
- 当List或者数组对象入参的时候,MyBatis是如何处理的?
resultType和resultMap的异同
- resultType:表示直接返回类型
基本数据类型
复杂数据类型(实体类对象,集合) - resultMap:对外部resultMap的引用
应用场景:
- 数据库字段与类对象中属性字段不一致
- 复杂的联合查询,自由控制映射结果
- 二者不能同时存在,即使同时存在,结果是以resultMap映射为基准
- resultMap和resultType都是Map的数据结构
- 数据库字段信息与对象属性不一致的时候,使用resultMap自定义映射
- 可以设置resultMap的自动映射的级别
动态SQL
- 基于OGNL表达式
- 完成多条件查询等逻辑实现
- 用于实现动态SQL的元素主要有如下:
- if
- trim
- where
- set
- choose(when、otherwise)
- foreach
3.1 resultMap映射
- 数据表system_userinfo:
- Java中实体类SystemUser对应数据库表system_usreinfo
public class SystemUser implements Serializable { /** * 用户ID */ private String userinfouid; /** * 登录名 */ private String userinfologinid; /** * 姓名 */ private String userinfoname; /** * 密码 */ private String userinfo_password; /** * 性别 */ private String userinfo_sex; /** * 电子邮箱 */ private String userinfo_email; /** * 手机 */ private String userinfo_mobile; /** * 用户状态(1 正常 2 锁定 3注销) */ private int userinfo_status; /** * 用户角色id */ private String userinfo_roleid; /** * 用户角色名 */ private String userinfo_rolename; }
if标签(判断参数) 实现简单的条件判断
- SystemUserMapper.xml
<!--根据用户id和性别两个字段查询,两个字段可同时存在,也可同时为空,也可单独存在--> <select id="selectByUidOrSex" parameterType="com.ebuy.pojo.SystemUser" resultMap="userMap"> select * from system_userinfo where 1 = 1 <if test="userinfouid != '' and userinfouid != null"> and userinfo_uid = #{userinfouid} </if> <if test="userinfo_sex != '' and userinfo_sex != null"> and userinfo_sex = #{userinfo_sex} </if> </select>
- SystemUserMapper接口
/** * 根据用户id和性别两个字段查询,两个字段可同时存在,也可同时为空,也可单独存在 * @param userinfouid * @param userinfo_sex * @return */ SystemUser selectByUidOrSex(@Param("userinfouid")String userinfouid,@Param("userinfo_sex")String userinfo_sex);
- SystemUserMapperTest
@Test public void selectByUidOrSex(){ SqlSession sqlSession = MyBatisUtil.createSqlSession(); SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class); SystemUser systemUser = systemUserMapper.selectByUidOrSex("1",""); System.out.println(systemUser); MyBatisUtil.closeSqlSession(sqlSession); }
if+where改造SQL语句
- SystemUserMapper.xml
<!--用where语句改进--> <!--根据用户id和性别两个字段查询,两个字段可同时存在,也可同时为空,也可单独存在--> <select id="selectByUidOrSex2" parameterType="com.ebuy.pojo.SystemUser" resultMap="userMap"> select * from system_userinfo <where> <if test="userinfouid != '' and userinfouid != null"> and userinfo_uid = #{userinfouid} </if> <if test="userinfo_sex != '' and userinfo_sex != null"> and userinfo_sex = #{userinfo_sex} </if> </where> </select>
- SystemUserMapper接口
/** * 根据用户id和性别两个字段查询,两个字段可同时存在,也可同时为空,也可单独存在 * @param userinfouid * @param userinfo_sex * @return */ SystemUser selectByUidOrSex2(@Param("userinfouid")String userinfouid,@Param("userinfo_sex")String userinfo_sex);
- SystemUserMapperTest
@Test public void selectByUidOrSex2(){ SqlSession sqlSession = MyBatisUtil.createSqlSession(); SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class); SystemUser systemUser = systemUserMapper.selectByUidOrSex2("1",""); System.out.println(systemUser); MyBatisUtil.closeSqlSession(sqlSession); }
3.5 更新用户表信息,若某个参数为null,则不需要更新,保持数据库原值(使用if+set标签)
- SystemUserMapper.xml
<!--更新用户信息,传入几个参数,就更新几个,判断出几个长修改参数--> <update id="updateUserById" parameterType="com.ebuy.pojo.SystemUser"> update system_userinfo <set> <if test="userinfoname != '' and userinfoname != null"> userinfo_name = #{userinfoname}, </if> <if test="userinfo_password != '' and userinfo_password != null"> userinfo_password = #{userinfo_password}, </if> <if test="userinfo_email != '' and userinfo_email != null"> userinfo_email = #{userinfo_email}, </if> <if test="userinfo_mobile != '' and userinfo_mobile != null"> userinfo_mobile = #{userinfo_mobile} </if> </set> where userinfo_uid = #{userinfouid} </update>
- SystemUserMapper接口
/** * 根据用户id更新用户信息 * @param systemUser * @return */ int updateUserById(SystemUser systemUser);
- SystemUserMapperTest
@Test public void updateUserById(){ SqlSession sqlSession = MyBatisUtil.createSqlSession(); SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class); SystemUser systemUser = new SystemUser(); systemUser.setUserinfouid("5"); systemUser.setUserinfoname("王五3号"); systemUser.setUserinfo_password("1234567"); systemUser.setUserinfo_email("haha@163.com"); systemUser.setUserinfo_mobile("110"); int r = systemUserMapper.updateUserById(systemUser); sqlSession.commit(); System.out.println(r); MyBatisUtil.closeSqlSession(sqlSession); }
trim标签的作用
- 属性
prefix
suffix
prefixOverrides
suffixOverrides - 更灵活的去除关键字
- 替代where和set
3.6 更新用户表信息,若某个参数为null,则不需要更新,保持数据库原值(使用if+trim标签替代if+set效果一样)
- SystemUserMapper.xml
<!--更新用户信息2,使用trim方式--> <update id="updateUserById2" parameterType="com.ebuy.pojo.SystemUser"> update system_userinfo <trim prefix="set" prefixOverrides="," suffix="where userinfo_uid = #{userinfouid}"> <if test="userinfoname != '' and userinfoname != null"> userinfo_name = #{userinfoname}, </if> <if test="userinfo_password != '' and userinfo_password != null"> userinfo_password = #{userinfo_password}, </if> <if test="userinfo_email != '' and userinfo_email != null"> userinfo_email = #{userinfo_email}, </if> <if test="userinfo_mobile != '' and userinfo_mobile != null"> userinfo_mobile = #{userinfo_mobile} </if> </trim> </update>
3.7 在where条件语句不确定的情况下,判断是否拼接where语句,并且动态删除and 或者 or关键字(if+trim标签组合)
-
SystemUserMapper.xml
<!--在where条件语句不确定的情况下使用,动态删除前面的and 或 or关键字--> <select id="getUserList" resultMap="userMap"> select * from system_userinfo <!--prefix是前缀,prefixOverrides是要替换掉的连接关键字--> <trim prefix="where" prefixOverrides ="and|or"> <if test="userinfoname != '' and userinfoname != null"> or userinfo_name = #{userinfoname} </if> <if test="userinfo_password != '' and userinfo_password != null"> and userinfo_password = #{userinfo_password} </if> </trim> </select>
-
SystemUserMapper接口
/** * 在where条件语句不确定的情况下使用 * 根据用户名和密码 * @param userifnoname * @param userinfo_password * @return */ List<SystemUser> getUserList(@Param("userinfoname")String userifnoname,@Param("userinfo_password")String userinfo_password );
-
SystemUserMapperTest
@Test public void getUserList(){ SqlSession sqlSession = MyBatisUtil.createSqlSession(); SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class); List<SystemUser> systemUserList = systemUserMapper.getUserList("张三",""); System.out.println(systemUserList); MyBatisUtil.closeSqlSession(sqlSession); }
foreach标签
- 迭代一个集合,通常用于in条件
- 属性
item
index
collection:必须指定- list
- array
- map-key
open
separator
close
3.8 使用foreach标签,遍历Array数组,实现SQL语句中,in关键字的作用
- SystemUserMapper.xml
<!--使用foreach标签,遍历Array数组,实现SQL语句中,in关键字的作用--> <!--select * from system_userinfo where userinfo_roleId in (1,2,3)--> <select id="selectUserByArray" resultMap="userMap"> select * from system_userinfo where userinfo_roleId in <foreach collection="array" item="roleIdsArray" open="(" separator="," close=")"> #{roleIdsArray} </foreach> </select>
- SystemUserMapper接口
/** * 使用foreach标签,遍历Array数组,实现SQL语句中,in关键字的作用 * @param roleIdsArray * @return */ List<SystemUser> selectUserByArray(int[] roleIdsArray);
- SystemUserMapperTest
@Test public void selectUserByArray(){ SqlSession sqlSession = MyBatisUtil.createSqlSession(); SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class); int[] roleIdsArray = {1,2,3}; List<SystemUser> systemUserList = systemUserMapper.selectUserByArray(roleIdsArray); for(SystemUser systemUser:systemUserList){ System.out.println(systemUser); } MyBatisUtil.closeSqlSession(sqlSession); }
3.9 使用foreach标签,遍历List集合,实现SQL语句中,in关键字的作用
- SystemUserMapper.xml
<!--使用foreach标签,遍历List集合,实现SQL语句中,in关键字的作用--> <!--select * from system_userinfo where userinfo_roleId in (1,2,3)--> <select id="selectUserByList" resultMap="userMap"> select * from system_userinfo where userinfo_roleId in <foreach collection="list" item="roleIdsList" open="(" separator="," close=")"> #{roleIdsList} </foreach> </select>
- SystemUserMapper接口
/** * 使用foreach标签,遍历List集合,实现SQL语句中,in关键字的作用 * @param roleIdsList * @return */ List<SystemUser> selectUserByList(List<Integer> roleIdsList);
- SystemUserMapperTest
@Test public void selectUserByList(){ SqlSession sqlSession = MyBatisUtil.createSqlSession(); SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class); List<Integer> roleIdsList = new ArrayList<>(); roleIdsList.add(1); roleIdsList.add(2); roleIdsList.add(3); List<SystemUser> systemUserList = systemUserMapper.selectUserByList(roleIdsList); for(SystemUser systemUser:systemUserList){ System.out.println(systemUser); } MyBatisUtil.closeSqlSession(sqlSession); }
3.10 使用foreach标签,遍历Map集合,实现SQL语句中,in关键字的作用
- SystemUserMapper.xml
<!--使用foreach标签,遍历Map集合,实现SQL语句中,in关键字的作用--> <!--select * from system_userinfo where userinfo_roleId in (1,2,3)--> <select id="selectUserByMap" resultMap="userMap"> select * from system_userinfo where userinfo_roleId in <foreach collection="mapRoleIdsList" item="roleIdsList" open="(" separator="," close=")"> #{roleIdsList} </foreach> </select>
- SystemUserMapper接口
/** * 使用foreach标签,遍历Map集合,实现SQL语句中,in关键字的作用 * @param roleIdsMap * @return */ List<SystemUser> selectUserByMap(Map<String,Object> roleIdsMap);
- SystemUserMapperTest
@Test public void selectUserByMap(){ SqlSession sqlSession = MyBatisUtil.createSqlSession(); SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class); /*List<Integer> roleIdsList = new ArrayList<>(); roleIdsList.add(1); roleIdsList.add(2); roleIdsList.add(3);*/ /** * 创建list集合也可以使用Arrays的内部方法,更为简便 */ List roleIdsList = Arrays.asList(1,2,3); Map<String,Object> mapRoleIdsList = new HashMap<>(); mapRoleIdsList.put("mapRoleIdsList", roleIdsList); List<SystemUser> systemUserList = systemUserMapper.selectUserByMap(mapRoleIdsList); for(SystemUser systemUser:systemUserList){ System.out.println(systemUser); } MyBatisUtil.closeSqlSession(sqlSession); }
choose(when、otherwise)
- 相当于Java中switch语句
- 当when有条件满足时,就跳出choose,不再执行后面的when和otherwise
3. 11 使用choose与when方式,与if标签不同之处在于,当其中一个when条件满足后,就不在执行后面的when语句
- SystemUserMapper.xml
<!--使用choose与when方式--> <!--与if标签不同之处在于,当其中一个when条件满足后,就不在执行后面的when语句--> <select id="selectUserByChoose" resultMap="userMap"> select * from system_userinfo where 1=1 <choose> <when test="userinfoname!=null and userinfoname!=''"> and userinfo_name like concat(concat('%',#{userinfoname}),'%') </when> <when test="userinfo_sex !=null and userinfo_sex!=''"> and userinfo_sex=#{userinfo_sex} </when> <otherwise> and 2=2 </otherwise> </choose> </select>
- SystemUserMapper接口
/** * * @param userinfoname * @param userinfo_sex * @return */ List<SystemUser> selectUserByChoose(@Param("userinfoname")String userinfoname,@Param("userinfo_sex")String userinfo_sex);
- SystemUserMapperTest
@Test public void selectUserByChoose(){ SqlSession sqlSession = MyBatisUtil.createSqlSession(); SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class); List<SystemUser> systemUserList = systemUserMapper.selectUserByChoose("",""); for(SystemUser systemUser:systemUserList){ System.out.println(systemUser); } MyBatisUtil.closeSqlSession(sqlSession); }
3.12 分页查询
- SystemUserMapper.xml
<!--分页查询--> <!-- start是起始记录数 end是结尾记录数 < 代表小于号 > 代表大于号 --> <select id="selectUserByStartAndEnd" resultMap="userMap"> select * from ( select t.*以上是关于MyBatis之动态SQL的主要内容,如果未能解决你的问题,请参考以下文章