MyBatis动态SQL(转载)
本文转载自:https://zhuanlan.zhihu.com/p/40530920,略做修改
一、前言
什么是 Mybatis 动态 SQL 呢?
根据用户提供的参数,动态决定查询语句依赖的条件或者SQL语句的具体内容,这就是动态SQL。
本文主要介绍 Mybatis 动态 SQL的四种主要标签组合:
- if、where
- choose、when、otherwise
- trim、where、set
- foreach
这些标签在开发过程中无处不在,能够解决数据查询方面的绝大部分问题;有了它们,你的 SQL 才更灵活。
二、首生成数据结构和测试数据(MySQL)
CREATE TABLE `dept` ( `DEPTNO` INT NOT NULL AUTO_INCREMENT, `DNAME` VARCHAR(45) NOT NULL, `LOC` VARCHAR(45) NOT NULL, `DATE` DATE NULL, `CITY` VARCHAR(45) NULL, PRIMARY KEY (`DEPTNO`), UNIQUE INDEX `DNAME_UNIQUE` (`DNAME` ASC)); INSERT INTO `dept` (`DEPTNO`, `DNAME`, `LOC`, `DATE`, `CITY`) VALUES ('1', '开发部', '上海开发中心', '2021-1-1', '上海'); INSERT INTO `dept` (`DEPTNO`, `DNAME`, `LOC`, `DATE`, `CITY`) VALUES ('2', '市场部', '北京市场中心', '2019-1-1', '北京'); INSERT INTO `dept` (`DEPTNO`, `DNAME`, `LOC`, `DATE`, `CITY`) VALUES ('3', '财务部', '北京天通苑', '2020-1-1', '北京'); INSERT INTO `dept` (`DEPTNO`, `DNAME`, `LOC`, `DATE`, `CITY`) VALUES ('4', '营销部', '上海虹桥', '2018-1-1', '上海');
三、动态 SQL 标签
(一)if 标签和 where 标签的使用
1. xml 代码:
<select id="findList1" resultType="Dept"> select deptno,dname,loc,date from dept <where> <if test="deptno != null and deptno != 0"> and deptno = #{deptno} </if> <if test="dname != null and dname != ''"> and dname = #{dname} </if> <if test="loc != null and loc != ''"> and loc = #{loc} </if> </where> </select>
2. Java 接口代码:
List<Dept> findList1(Dept dept);
3. Java测试代码:
@Test public void test01() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); Dept dept = new Dept(); dept.setDeptno(2); dept.setDname("市场部"); List<Dept> list = deptMapper.findList1(dept); list.forEach(item -> System.out.println(item)); }
4. 运行结果:
被拦截方法执行之前,做的辅助服务······ [DEBUG] Opening JDBC Connection [DEBUG] Created connection 1516500233. [DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a63f509] [DEBUG] ==> Preparing: select deptno,dname,loc,date from dept WHERE deptno = ? and dname = ? [DEBUG] ==> Parameters: 2(Integer), 市场部(String) [DEBUG] <== Total: 1 被拦截方法执行之后,做的辅助服务······ Dept{deptno=2, dname='市场部', loc='北京市场中心', city='null', date=Tue Jan 01 00:00:00 CST 2019} [DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a63f509] [DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a63f509] [DEBUG] Returned connection 1516500233 to pool.
5. 解读日志
我们只给 deptno 和 dname 进行了赋值,而没有对 loc 属性进行赋值,所以在 SQL 参数中没有出现 loc 字段,也就表名 loc 为空,导致 “and loc = #{loc}”没有被执行。
一般开发列表业务的查询条件时,如果有多个查询条件,通常会使用 <if> 标签来进行控制。
<where> 标签可以自动的将第一个条件前面的逻辑运算符 (or ,and) 去掉,正如代码中写的,deptno 查询条件前面是有“and”关键字的,但是在打印出来的 SQL 中却没有,这就是 <where> 的作用。
(二)choose、when、otherwise 标签的使用
1. xml 代码:
<select id="findList2" resultType="Dept"> select deptno,dname,loc,date from dept <where> <choose> <when test="dname != null and dname != ''"> and dname like '%' #{dname} '%' </when> <when test="loc != null and loc != ''"> and loc = #{loc} </when> <otherwise> and deptno = #{deptno} </otherwise> </choose> </where> </select>
2. Java接口代码:
List<Dept> findList2(Dept dept);
3. Java测试代码:
@Test public void test02() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); Dept dept = new Dept(); dept.setDeptno(2); List<Dept> list = deptMapper.findList2(dept); list.forEach(item -> System.out.println(item)); }
4. 运行结果:
被拦截方法执行之前,做的辅助服务······ [DEBUG] Opening JDBC Connection [DEBUG] Created connection 1516500233. [DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a63f509] [DEBUG] ==> Preparing: select deptno,dname,loc,date from dept WHERE deptno = ? [DEBUG] ==> Parameters: 2(Integer) [DEBUG] <== Total: 1 被拦截方法执行之后,做的辅助服务······ Dept{deptno=2, dname='市场部', loc='北京市场中心', city='null', date=Tue Jan 01 00:00:00 CST 2019} [DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a63f509] [DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a63f509] [DEBUG] Returned connection 1516500233 to pool.
5. 解读日志
这三个标签需要组合在一起使用,类似于 Java 中的 switch、case、default。只有一个条件生效,也就是只执行满足的条件 when,没有满足的条件就执行 otherwise,表示默认条件。
这个应该很好理解吧。
这里我们的测试用例中只给出了一个参数就是 deptno,没有给出 dname 以及 loc 参数,所以直接执行了 otherwise 中的代码,这里就不再过多的进行赘述。
(三)set 标签的使用
1. xml 代码:
<update id="update"> update dept <set> <if test="dname != null and dname != ''"> dname = #{dname}, </if> <if test="loc != null and loc != ''"> loc = #{loc}, </if> </set> where deptno = #{deptno} </update>
2. Java接口代码:
void update(Dept dept);
3. Java测试代码:
@Test public void test03() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); Dept dept = new Dept(); dept.setDeptno(2); dept.setDname("河北香河中心"); deptMapper.update(dept); session.commit(); }
4. 运行结果:
[DEBUG] Opening JDBC Connection [DEBUG] Created connection 1923598304. [DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@72a7c7e0] [DEBUG] ==> Preparing: update dept SET dname = ? where deptno = ? [DEBUG] ==> Parameters: 河北香河中心(String), 2(Integer) [DEBUG] <== Updates: 1 [DEBUG] Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@72a7c7e0] [DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@72a7c7e0] [DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@72a7c7e0] [DEBUG] Returned connection 1923598304 to pool.
5. 解读日志
<set> 标签会在成功拼接的条件前加上 SET 单词且最后一个“,”号会被无视掉,如 xml 代码中所示,“loc = #{loc},”代码并没有被执行,而“dname = #{dname}”代码后面的“,”已经被去掉了,这就是 <set> 的作用。
在进行表单更新的操作中,哪个字段中有值才去更新,没有值就不做任何操作,这就需要结合使用 <set> 标签和 <if> 标签了。
(四)trim 标签的使用
先说一下 trim 标签4个参数:
- prefix:前缀
- prefixOverrides:去掉第一个and或者是or
- suffix:后缀
- suffixOverrides:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)
1. xml 代码:
<!-- prefix:前缀 prefixOverrides:去掉第一个and或者是or suffix:后缀 suffixOverrides:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样) --> <select id="findList3" resultType="Dept"> select deptno,dname,loc,date from dept <trim prefix="where" prefixOverrides="and | or" suffix="order by deptno" suffixOverrides=","> <if test="deptno != null and deptno != 0"> and deptno = #{deptno} </if> <if test="dname != null and dname != ''"> and dname = #{dname} </if> <if test="loc != null and loc != ''"> and loc = #{loc} </if> </trim> </select>
2. Java接口代码:
List<Dept> findList3(Dept dept);
3. Java测试代码:
@Test public void test04() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); Dept dept = new Dept(); dept.setDeptno(1); dept.setDname("开发部"); List<Dept> list = deptMapper.findList3(dept); list.forEach(item -> System.out.println(item)); }
4. 运行结果:
被拦截方法执行之前,做的辅助服务······ [DEBUG] Opening JDBC Connection [DEBUG] Created connection 1516500233. [DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a63f509] [DEBUG] ==> Preparing: select deptno,dname,loc,date from dept where deptno = ? and dname = ? order by deptno [DEBUG] ==> Parameters: 1(Integer), 开发部(String) [DEBUG] <== Total: 1 被拦截方法执行之后,做的辅助服务······ Dept{deptno=1, dname='开发部', loc='上海开发中心', city='null', date=Fri Jan 01 00:00:00 CST 2021} [DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a63f509] [DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5a63f509] [DEBUG] Returned connection 1516500233 to pool.
5. 解读日志
<trim> 标签是一个格式化的标签,可以完成 <set> 或者是 <where> 标记的功能,从打印出的 SQL 语句中可以看出。
我们代码中并没有写“where”,但是打印出的 SQL 中却有,这是为什么呢?
这是因为 <trim> 标签中 prefix="where" 属性的缘故,这就是它的作用,而后面的 “order by deptno”,则是由于 suffix="order by deptno" 属性的缘故,prefixOverrides="and | or" 和 suffixOverrides="," 则与 <where> 和 <set> 作用相同。
(五)foreach 标签的使用
对于 <foreach> 标签,我们会根据4个例子来进行演示,主要有批量插入,list 集合参数、array 集合参数以及 map 集合参数。我们先来看一下 <foreach> 标签的参数:
- item:表示集合中每一个元素进行迭代的别名
- index:指定一个名字,用于表示在迭代过程中,每次迭代到的位置
- open:表示该语句以什么开始
- close:表示该语句以什么结束
- separator:表示每次进行迭代之间以什么符号做为分隔符
1)批量插入
1. xml 代码:
<!-- item:表示集合中每一个元素进行迭代的别名 index:指定一个名字,用于表示在迭代过程中,每次迭代到的位置 open:表示该语句以什么开始 close:表示该语句以什么结束 separator:表示每次进行迭代之间以什么符号做为分隔符 --> <insert id="insertBatch"> INSERT INTO dept (dname,loc) VALUES <foreach collection="list" item="dept" separator=","> (#{dept.dname},#{dept.loc}) </foreach> </insert>
2. Java接口代码:
void insertBatch(List<Dept> deptList);
3. Java测试代码:
@Test public void test05() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); List<Dept> deptList = new ArrayList<>(); Dept dept = new Dept(); dept.setDname("技术研发部"); dept.setLoc("聊城"); deptList.add(dept); dept = new Dept(); dept.setDname("科技事业部"); dept.setLoc("济南"); deptList.add(dept); deptMapper.insertBatch(deptList); session.commit(); }
4. 运行结果:
[DEBUG] Opening JDBC Connection [DEBUG] Created connection 1629687658. [DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@61230f6a] [DEBUG] ==> Preparing: INSERT INTO dept (dname,loc) VALUES (?,?) , (?,?) [DEBUG] ==> Parameters: 技术研发部(String), 聊城(String), 科技事业部(String), 济南(String) [DEBUG] <== Updates: 2 [DEBUG] Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@61230f6a] [DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@61230f6a] [DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@61230f6a] [DEBUG] Returned connection 1629687658 to pool.
5. 解读日志
从结果可以看出,我们一下插入了两条数据,每条数据之间使用“,”进行分割,separator="," 的作用就是如此,批量插入操作在日常的开发中也是经常使用的,也是必须掌握的知识点。
2)list 集合参数
1. xml 代码:
<select id="findList4" resultType="Dept"> select deptno,dname,loc,date from dept where deptno in <foreach collection="list" item="deptno" open="(" close=")" separator=","> #{deptno} </foreach> </select>
2. Java接口代码:
List<Dept> findList4(List<Integer> deptnoList);
3. Java测试代码:
@Test public void test06() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); List<Integer> deptnoList = new ArrayList<>(); deptnoList.add(5); deptnoList.add(6); List<Dept> list = deptMapper.findList4(deptnoList); list.forEach(item -> System.out.println(item)); }
4. 运行结果:
被拦截方法执行之前,做的辅助服务······ [DEBUG] Opening JDBC Connection [DEBUG] Created connection 1882554559. [DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@703580bf] [DEBUG] ==> Preparing: select deptno,dname,loc,date from dept where deptno in ( ? , ? ) [DEBUG] ==> Parameters: 5(Integer), 6(Integer) [DEBUG] <== Total: 2 被拦截方法执行之后,做的辅助服务······ Dept{deptno=5, dname='技术研发部', loc='聊城', city='null', date=null} Dept{deptno=6, dname='科技事业部', loc='济南', city='null', date=null} [DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@703580bf] [DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@703580bf] [DEBUG] Returned connection 1882554559 to pool
5. 解读日志
从打印的 SQL 语句可以看出,这个 <foreach> 标签为我们提供了这样一段 SQL 代码:( ? , ? ) ,前后的括号由 open="(" close=")" 进行控制,内涵两个循环遍历出的元素,用“?”占位符占位,并用“,”隔开。array 集合与 list 及其相似,这里给出 SQL 语句、接口、调用,就不再多赘述了。
<select id="findList5" resultType="Dept"> select deptno,dname,loc,date from dept where deptno in <foreach collection="array" item="deptno" open="(" close=")" separator=","> #{deptno} </foreach> </select>
List<Dept> findList5(int[] deptnos);
@Test public void test07() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); int[] deptnos = new int[2]; deptnos[0] = 5; deptnos[1] = 6; List<Dept> list = deptMapper.findList5(deptnos); list.forEach(item -> System.out.println(item)); }
3)map 集合参数
1. xml 代码:
<select id="findList6" resultType="Dept"> select deptno,dname,loc,date from dept where deptno in <foreach collection="myMap.values" item="deptno" open="(" close=")" separator=","> #{deptno} </foreach> </select>
2. Java接口代码:
List<Dept> findList6(@Param("myMap") Map<String, Integer> map);
3. Java测试代码:
@Test public void test08() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); Map<String, Integer> map = new HashMap<>(); map.put("key1",5); map.put("key2",6); List<Dept> list = deptMapper.findList6(map); list.forEach(item -> System.out.println(item)); }
4. 运行结果:
被拦截方法执行之前,做的辅助服务······ [DEBUG] Opening JDBC Connection [DEBUG] Created connection 1629687658. [DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@61230f6a] [DEBUG] ==> Preparing: select deptno,dname,loc,date from dept where deptno in ( ? , ? ) [DEBUG] ==> Parameters: 5(Integer), 6(Integer) [DEBUG] <== Total: 2 被拦截方法执行之后,做的辅助服务······ Dept{deptno=5, dname='技术研发部', loc='聊城', city='null', date=null} Dept{deptno=6, dname='科技事业部', loc='济南', city='null', date=null} [DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@61230f6a] [DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@61230f6a] [DEBUG] Returned connection 1629687658 to pool.
5. 解读日志
从结果我们可以看出,打印出的 SQL 与 list 参数的结果是完全一致的,这里我们使用到了 Mybatis 的参数注解 @Param(),在这里这个参数是必不可少的。
因为 <foreach> 标签中的 collection="myMap.values" 属性是这样写的,我们要告知 Mybatis “myMap”是一个参数对象,而我们用的则是这个对象中的“values”,就相当于 Java 中我们的 map 对象调用 values 对象(Collection<Integer> values = map.values();),这里就相当于是对这个 values 集合进行遍历。
四、总结
动态 SQL 的标签就这些,我们已经都讲解过了,内容还是比较多的,一定要自己动手写一写单元测试,并且掌握每一种标签的不同使用场景,学会了他们,解决日常开发中的业务逻辑就会轻松很多。
五、全部代码下载
Dept.java
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package top.alanshelby.mybatis.bean; import java.util.Date; public class Dept { private Integer deptno; private String dname; private String loc; private Date date; private String city; public Integer getDeptno() { return deptno; } public void setDeptno(Integer deptno) { this.deptno = deptno; } public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } @Override public String toString() { return "Dept{" + "deptno=" + deptno + ", dname='" + dname + '\'' + ", loc='" + loc + '\'' + ", city='" + city + '\'' + ", date=" + date + '}'; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } }
DeptMapper.java
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package top.alanshelby.mybatis.dao; import org.apache.ibatis.annotations.Param; import top.alanshelby.mybatis.bean.Dept; import java.util.List; import java.util.Map; public interface DeptMapper { List<Dept> findList1(Dept dept); List<Dept> findList2(Dept dept); void update(Dept dept); List<Dept> findList3(Dept dept); void insertBatch(List<Dept> deptList); List<Dept> findList4(List<Integer> deptnoList); List<Dept> findList5(int[] deptnos); List<Dept> findList6(@Param("myMap") Map<String, Integer> map); }
MyInterceptor.java
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package top.alanshelby.mybatis.util; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.*; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import java.util.Properties; @Intercepts( @Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class} ) ) public class MyInterceptor implements Interceptor { /** * @param invocation { 代理对象,被监控方法对象,当前被监控方法运行时需要的实参 } * @return * @throws Throwable */ @Override public Object intercept(Invocation invocation) throws Throwable { System.out.println("被拦截方法执行之前,做的辅助服务······"); Object proceed = invocation.proceed(); System.out.println("被拦截方法执行之后,做的辅助服务······"); return proceed; } /** * @param target 表示被拦截的对象,此处为 Executor 的实例对象 * 作用:如果被拦截对象所在的类有实现接口,就为当前拦截对象生成一个代理对象 * 如果被拦截对象所在的类没有指定接口,这个对象之后的行为就不会被代理操作 * @return */ @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } }
AppTest.java
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package top.alanshelby; 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.After; import org.junit.Before; import org.junit.Test; import top.alanshelby.mybatis.bean.Dept; import top.alanshelby.mybatis.dao.DeptMapper; import java.io.IOException; import java.io.InputStream; import java.util.*; public class AppTest { private SqlSession session; @Before public void start() { try { InputStream inputStream = Resources.getResourceAsStream("myBatis-config_top.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); session = factory.openSession(); } catch (Exception exception) { exception.printStackTrace(); } } @Test public void test01() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); Dept dept = new Dept(); dept.setDeptno(2); dept.setDname("市场部"); List<Dept> list = deptMapper.findList1(dept); list.forEach(item -> System.out.println(item)); } @Test public void test02() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); Dept dept = new Dept(); dept.setDeptno(2); List<Dept> list = deptMapper.findList2(dept); list.forEach(item -> System.out.println(item)); } @Test public void test03() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); Dept dept = new Dept(); dept.setDeptno(2); dept.setDname("河北香河中心"); deptMapper.update(dept); session.commit(); } @Test public void test04() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); Dept dept = new Dept(); dept.setDeptno(1); dept.setDname("开发部"); List<Dept> list = deptMapper.findList3(dept); list.forEach(item -> System.out.println(item)); } @Test public void test05() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); List<Dept> deptList = new ArrayList<>(); Dept dept = new Dept(); dept.setDname("技术研发部"); dept.setLoc("聊城"); deptList.add(dept); dept = new Dept(); dept.setDname("科技事业部"); dept.setLoc("济南"); deptList.add(dept); deptMapper.insertBatch(deptList); session.commit(); } @Test public void test06() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); List<Integer> deptnoList = new ArrayList<>(); deptnoList.add(5); deptnoList.add(6); List<Dept> list = deptMapper.findList4(deptnoList); list.forEach(item -> System.out.println(item)); } @Test public void test07() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); int[] deptnos = new int[2]; deptnos[0] = 5; deptnos[1] = 6; List<Dept> list = deptMapper.findList5(deptnos); list.forEach(item -> System.out.println(item)); } @Test public void test08() throws IOException { DeptMapper deptMapper = session.getMapper(DeptMapper.class); Map<String, Integer> map = new HashMap<>(); map.put("key1",5); map.put("key2",6); List<Dept> list = deptMapper.findList6(map); list.forEach(item -> System.out.println(item)); } @After public void end() { if (session != null) { session.close(); } } }
DeptMapper.xml
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="top.alanshelby.mybatis.dao.DeptMapper"> <select id="findList1" resultType="Dept"> select deptno,dname,loc,date from dept <where> <if test="deptno != null and deptno != 0"> and deptno = #{deptno} </if> <if test="dname != null and dname != ''"> and dname = #{dname} </if> <if test="loc != null and loc != ''"> and loc = #{loc} </if> </where> </select> <select id="findList2" resultType="Dept"> select deptno,dname,loc,date from dept <where> <choose> <when test="dname != null and dname != ''"> and dname like '%' #{dname} '%' </when> <when test="loc != null and loc != ''"> and loc = #{loc} </when> <otherwise> and deptno = #{deptno} </otherwise> </choose> </where> </select> <update id="update"> update dept <set> <if test="dname != null and dname != ''"> dname = #{dname}, </if> <if test="loc != null and loc != ''"> loc = #{loc}, </if> </set> where deptno = #{deptno} </update> <!-- prefix:前缀 prefixOverrides:去掉第一个and或者是or suffix:后缀 suffixOverrides:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样) --> <select id="findList3" resultType="Dept"> select deptno,dname,loc,date from dept <trim prefix="where" prefixOverrides="and | or" suffix="order by deptno" suffixOverrides=","> <if test="deptno != null and deptno != 0"> and deptno = #{deptno} </if> <if test="dname != null and dname != ''"> and dname = #{dname} </if> <if test="loc != null and loc != ''"> and loc = #{loc} </if> </trim> </select> <!-- item:表示集合中每一个元素进行迭代的别名 index:指定一个名字,用于表示在迭代过程中,每次迭代到的位置 open:表示该语句以什么开始 close:表示该语句以什么结束 separator:表示每次进行迭代之间以什么符号做为分隔符 --> <insert id="insertBatch"> INSERT INTO dept (dname,loc) VALUES <foreach collection="list" item="dept" separator=","> (#{dept.dname},#{dept.loc}) </foreach> </insert> <select id="findList4" resultType="Dept"> select deptno,dname,loc,date from dept where deptno in <foreach collection="list" item="deptno" open="(" close=")" separator=","> #{deptno} </foreach> </select> <select id="findList5" resultType="Dept"> select deptno,dname,loc,date from dept where deptno in <foreach collection="array" item="deptno" open="(" close=")" separator=","> #{deptno} </foreach> </select> <select id="findList6" resultType="Dept"> select deptno,dname,loc,date from dept where deptno in <foreach collection="myMap.values" item="deptno" open="(" close=")" separator=","> #{deptno} </foreach> </select> </mapper>
myBatis-config_top.xml
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="db.properties"></properties> <typeAliases> <package name="top.alanshelby.mybatis.bean"/> </typeAliases> <typeHandlers> <typeHandler handler="top.alanshelby.mybatis.util.MyDateTypeHandler" javaType="java.util.Date" jdbcType="VARCHAR"/> </typeHandlers> <plugins> <plugin interceptor="top.alanshelby.mybatis.util.MyInterceptor"></plugin> </plugins> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <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> <package name="top.alanshelby.mybatis.dao"/> </mappers> </configuration>
db.properties
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/xuejia?useUnicode=true&characterEncoding=utf-8 jdbc.username=root jdbc.password=admin
log4j.properties
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
##define an appender named console log4j.appender.console=org.apache.log4j.ConsoleAppender #The Target value is System.out or System.err log4j.appender.console.Target=System.out #set the layout type of the apperder log4j.appender.console.layout=org.apache.log4j.PatternLayout #set the layout format pattern log4j.appender.console.layout.ConversionPattern=[%-5p] %m%n ##define a logger log4j.rootLogger=debug,console