文章目录
- 一、应用场景
- 二、代码演示
- 1、动态 **SQL** 之\<if>
- (1) 需求
- (2)代码
- 2、动态 **SQL** 之\<choose>
- (1) 需求
- (2)代码
- 3、动态 **SQL** 之\<set>
- (1) 需求
- (2)代码
- 4、动态 **SQL** 之\<foreach>
- (1) 需求
- (2)代码
一、应用场景
根据不同的条件,来执行不同的 sql 语句的时候,需要用到动态sql。
二、代码演示
1、动态 SQL 之<if>
(1) 需求
根据id 和username 查询,但是不确定两个都有值。
(2)代码
-
数据库环境
CREATE DATABASE `mybatis_db`; USE `mybatis_db`; CREATE TABLE `user` (`id` INT(11) NOT NULL AUTO_INCREMENT,`username` VARCHAR(32) NOT NULL COMMENT '用户名称',`birthday` DATETIME DEFAULT NULL COMMENT '生日',`sex` CHAR(1) DEFAULT NULL COMMENT '性别',`address` VARCHAR(256) DEFAULT NULL COMMENT '地址',PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8;-- insert.... INSERT INTO USER(id,username,birthday,sex,address) VALUES (1,'tom','2024-01-01 00:00:00','男','北京'),(2,'jerry','2023-01-01 00:00:00','男','上海');
-
pom依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>mybatis-dao</artifactId><version>1.0-SNAPSHOT</version><!--指定编码及版本--><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.encoding>UTF-8</maven.compiler.encoding><java.version>1.11</java.version><maven.compiler.source>1.11</maven.compiler.source><maven.compiler.target>1.11</maven.compiler.target></properties><!--引入相关依赖--><dependencies><!--引入mybatis依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.3</version></dependency><!--引入mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!--引入junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies></project>
-
SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><properties resource="jdbc.properties"></properties><typeAliases><!--方式一:给单个实体起别名--> <!-- <typeAlias type="domain.User" alias="user"></typeAlias>--><!--方式二:批量起别名 别名就是类名,且不区分大小写--><package name="domain"/></typeAliases><!--环境配置--><environments default="mysql"><!--使用mysql环境--><environment id="mysql"><!--使用jdbc事务管理亲--><transactionManager type="JDBC"></transactionManager><!-- 使用连接池--><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><!--加载映射配置--><mappers><mapper resource="mapper/UserMapper.xml"></mapper></mappers></configuration>
-
User实体类
package domain;import java.util.Date;public class User {private Integer id;private String usernameabc;private Date birthday;private String sex;private String address;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getUsernameabc() {return usernameabc;}public void setUsernameabc(String usernameabc) {this.usernameabc = usernameabc;}@Overridepublic String toString() {return "User{" +"id=" + id +", usernameabc='" + usernameabc + '\'' +", birthday=" + birthday +", sex='" + sex + '\'' +", address='" + address + '\'' +'}';} }
-
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mapper.UserMapper"><!--id : 标签的唯一标识type: 封装后实体类型--><resultMap id="userResultMap" type="domain.User"><!--手动配置映射关系--><!--id: 用来配置主键--><id property="id" column="id"></id><!-- result: 表中普通字段的封装--><result property="usernameabc" column="username"></result><result property="birthday" column="birthday"></result><result property="sex" column="sex"></result><result property="address" column="address"></result></resultMap><!--动态 SQL 之<if>--><!--where 标签相当于 where 1=1,但是如果没有条件,就不会拼接where 关键字--><select id="findByIdAndUsernameIf" parameterType="user" resultMap="userResultMap">select * from user<where><if test="id != null">and id = #{id}</if><if test="usernameabc != null">and username = #{usernameabc}</if></where></select></mapper>
-
UserMapper.java
package mapper;import domain.User;import java.util.List;public interface UserMapper {public List<User> findByIdAndUsernameIf(User user);}
-
测试类
package test;import domain.User; import mapper.UserMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test;import java.io.InputStream; import java.util.List;public class MybatisTest {//动态 SQL 之<if>@Testpublic void testFindByIdAndUsernameIf() throws Exception {InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User(); // user.setUsernameabc("tom");user.setId(1);List<User> users = mapper.findByIdAndUsernameIf(user);for (User user1 : users) {System.out.println(user1);}sqlSession.close();}}
-
测试结果
可以只有name或者只有id,或者两者都没有
2、动态 SQL 之<choose>
(1) 需求
如果有id 只使用id 做查询,没有 id 的话看是否有username,有username 就根据username 做查询, 如果都没有,就不带条件
(2)代码
-
UserMapper.java
package mapper;import domain.User;import java.util.List;public interface UserMapper {public List<User> findByIdAndUsernameIf(User user);public List<User> findByIdAndUsernameChoose(User user);}
-
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mapper.UserMapper"><!--id : 标签的唯一标识type: 封装后实体类型--><resultMap id="userResultMap" type="domain.User"><!--手动配置映射关系--><!--id: 用来配置主键--><id property="id" column="id"></id><!-- result: 表中普通字段的封装--><result property="usernameabc" column="username"></result><result property="birthday" column="birthday"></result><result property="sex" column="sex"></result><result property="address" column="address"></result></resultMap><!--动态 SQL 之<choose>--><!--choose 标签相当于swtich 语句when 标签相当于case 语句otherwise 标签相当于default 语句--><select id="findByIdAndUsernameChoose" parameterType="user" resultMap="userResultMap">select * from user<where><choose><when test="id != null">and id = #{id}</when><when test="usernameabc != null">and username = #{usernameabc}</when><otherwise>and 1 = 1</otherwise></choose></where></select></mapper>
-
测试类
package test;import domain.User; import mapper.UserMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test;import java.io.InputStream; import java.util.List;public class MybatisTest {//动态 SQL 之<if>@Testpublic void testFindByIdAndUsernameIf() throws Exception {InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User(); // user.setUsernameabc("tom");user.setId(1);List<User> users = mapper.findByIdAndUsernameIf(user);for (User user1 : users) {System.out.println(user1);}sqlSession.close();}//动态 SQL 之<choose>@Testpublic void testFindByIdAndUsernameChoose() throws Exception {InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User(); // user.setUsernameabc("tom");user.setId(1);List<User> users = mapper.findByIdAndUsernameChoose(user);for (User user1 : users) {System.out.println(user1);}sqlSession.close();}}
-
测试结果
3、动态 SQL 之<set>
(1) 需求
动态更新user 表数据,如果该属性有值就更新,没有值不做处理。
(2)代码
-
UserMapper.java
package mapper;import domain.User;import java.util.List;public interface UserMapper {public List<User> findByIdAndUsernameIf(User user);public List<User> findByIdAndUsernameChoose(User user);public void updateIf(User user);}
-
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mapper.UserMapper"><!--id : 标签的唯一标识type: 封装后实体类型--><resultMap id="userResultMap" type="domain.User"><!--手动配置映射关系--><!--id: 用来配置主键--><id property="id" column="id"></id><!-- result: 表中普通字段的封装--><result property="usernameabc" column="username"></result><result property="birthday" column="birthday"></result><result property="sex" column="sex"></result><result property="address" column="address"></result></resultMap><!--动态 SQL 之<if>--><!--where 标签相当于 where 1=1,但是如果没有条件,就不会拼接where 关键字--><select id="findByIdAndUsernameIf" parameterType="user" resultMap="userResultMap">select * from user<where><if test="id != null">and id = #{id}</if><if test="usernameabc != null">and username = #{usernameabc}</if></where></select><!--动态 SQL 之<choose>--><!--choose 标签相当于swtich 语句when 标签相当于case 语句otherwise 标签相当于default 语句--><select id="findByIdAndUsernameChoose" parameterType="user" resultMap="userResultMap">select * from user<where><choose><when test="id != null">and id = #{id}</when><when test="usernameabc != null">and username = #{usernameabc}</when><otherwise>and 1 = 1</otherwise></choose></where></select><!--动态 SQL 之<set>--><!--set 标签在更新的时候,自动加上set 关键字,然后去掉最后一个条件的逗号--><update id="updateIf" parameterType="user">update user<set><if test="usernameabc != null">username = #{usernameabc},</if><if test="birthday != null">birthday = #{birthday},</if><if test="sex != null">sex = #{sex},</if><if test="address != null">address = #{address},</if></set>where id = #{id}</update></mapper>
-
测试类
package test;import domain.User; import mapper.UserMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test;import java.io.InputStream; import java.util.List;public class MybatisTest {//动态 SQL 之<if>@Testpublic void testFindByIdAndUsernameIf() throws Exception {InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User(); // user.setUsernameabc("tom");user.setId(1);List<User> users = mapper.findByIdAndUsernameIf(user);for (User user1 : users) {System.out.println(user1);}sqlSession.close();}//动态 SQL 之<choose>@Testpublic void testFindByIdAndUsernameChoose() throws Exception {InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User(); // user.setUsernameabc("tom");user.setId(1);List<User> users = mapper.findByIdAndUsernameChoose(user);for (User user1 : users) {System.out.println(user1);}sqlSession.close();}//动态 SQL 之<set>@Testpublic void testupdateSet() throws Exception {InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setUsernameabc("jack");user.setBirthday(new Date());user.setSex("男");user.setAddress("深圳");user.setId(2);mapper.updateIf(user);sqlSession.commit();sqlSession.close();}}
-
测试结果
4、动态 SQL 之<foreach>
(1) 需求
foreach 主要是用来做数据的循环遍历。例如: select * from user where id in (1,2,3) 在这样的语句中,传入的参数部分必须依靠 foreach 遍历才能实现。
标签用于遍历集合,它的属性:
- collection:代表要遍历的集合元素
- open:代表语句的开始部分
- close:代表结束部分
- item:代表遍历集合的每个元素,生成的变量名
- sperator:代表分隔符
(2)代码
- 集合
-
UserMapper.java
package mapper;import domain.User;import java.util.List;public interface UserMapper {public List<User> findByList(List<Integer> ids);}
-
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mapper.UserMapper"><!--id : 标签的唯一标识type: 封装后实体类型--><resultMap id="userResultMap" type="domain.User"><!--手动配置映射关系--><!--id: 用来配置主键--><id property="id" column="id"></id><!-- result: 表中普通字段的封装--><result property="usernameabc" column="username"></result><result property="birthday" column="birthday"></result><result property="sex" column="sex"></result><result property="address" column="address"></result></resultMap><!--动态 SQL 之<foreach> 集合--><!--如果查询条件为普通类型 List 集合,collection 属性值为:collection 或者 list--><select id="findByList" parameterType="list" resultMap="userResultMap">select * from user<where><foreach collection="collection" open="id in(" close=")" item="id" separator=",">#{id}</foreach></where></select></mapper>
-
测试类
package test;import domain.User; import mapper.UserMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test;import java.io.InputStream; import java.util.List;public class MybatisTest {//动态 SQL 之<foreach> 集合@Testpublic void testFindByList() throws Exception {InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<Integer> ids = new ArrayList<>();ids.add(1);ids.add(2);List<User> list = mapper.findByList(ids);System.out.println(list);sqlSession.close();}}
-
测试结果
- 数组
-
UserMapper.java
package mapper;import domain.User;import java.util.List;public interface UserMapper {public List<User> findByArray(Integer[] ids);}
-
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mapper.UserMapper"><!--id : 标签的唯一标识type: 封装后实体类型--><resultMap id="userResultMap" type="domain.User"><!--手动配置映射关系--><!--id: 用来配置主键--><id property="id" column="id"></id><!-- result: 表中普通字段的封装--><result property="usernameabc" column="username"></result><result property="birthday" column="birthday"></result><result property="sex" column="sex"></result><result property="address" column="address"></result></resultMap><!--动态 SQL 之<foreach> 数组--><!--如果查询条件为普通类型 Array 数组,collection 属性值为:array--><select id="findByArray" parameterType="list" resultMap="userResultMap">select * from user<where><foreach collection="array" open="id in(" close=")" item="id" separator=",">#{id}</foreach></where></select></mapper>
-
测试类
package test;import domain.User; import mapper.UserMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test;import java.io.InputStream; import java.util.List;public class MybatisTest {//动态 SQL 之<foreach> 数组@Testpublic void testFindByArray() throws Exception {InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);Integer[] ids = {1, 2};List<User> list = mapper.findByArray(ids);System.out.println(list);sqlSession.close();}}
-
测试结果
- pojo
-
创建pojo类,QueryVo
package domain;import java.util.List;public class QueryVo {private List<Integer> ids;public List<Integer> getIds() {return ids;}public void setIds(List<Integer> ids) {this.ids = ids;} }
-
UserMapper.java
package mapper;import domain.User;import java.util.List;public interface UserMapper {public List<User> findByQueryVo(QueryVo queryVo);}
-
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mapper.UserMapper"><!--id : 标签的唯一标识type: 封装后实体类型--><resultMap id="userResultMap" type="domain.User"><!--手动配置映射关系--><!--id: 用来配置主键--><id property="id" column="id"></id><!-- result: 表中普通字段的封装--><result property="usernameabc" column="username"></result><result property="birthday" column="birthday"></result><result property="sex" column="sex"></result><result property="address" column="address"></result></resultMap><!--动态 SQL 之<foreach> pojo--><!--如果查询条件为复杂类型pojo 对象,collection 属性值为:集合或数组的属性名--><select id="findByQueryVo" parameterType="queryVo" resultMap="userResultMap">select * from user<where><foreach collection="ids" open="id in(" close=")" item="id" separator=",">#{id}</foreach></where></select></mapper>
-
测试类
package test;import domain.User; import mapper.UserMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test;import java.io.InputStream; import java.util.List;public class MybatisTest {//动态 SQL 之<foreach> pojo@Testpublic void testFindByQueryVo() throws Exception {InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<Integer> ids = new ArrayList<>();ids.add(1);ids.add(2);QueryVo queryVo = new QueryVo();queryVo.setIds(ids);List<User> list = mapper.findByQueryVo(queryVo);System.out.println(list);sqlSession.close();}}
-
测试结果