第一章:简介

  • 动态SQL 是 Mybatis 强大特性之一。极大的简化我们拼装 SQL 的操作。
  • 动态SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。
  • Mybatis 采用功能强大的基于 OGNL 的表达式来简化操作。
    • if
    • choose(when、otherwise)
    • trim(where、set)
    • foreach

第二章:环境搭建

  • 导入相关 jar 包的 Maven 坐标:
  1. <dependency>
  2. <groupId>org.mybatis</groupId>
  3. <artifactId>mybatis</artifactId>
  4. <version>3.4.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>log4j</groupId>
  8. <artifactId>log4j</artifactId>
  9. <version>1.2.17</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>mysql</groupId>
  13. <artifactId>mysql-connector-java</artifactId>
  14. <version>8.0.21</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>junit</groupId>
  18. <artifactId>junit</artifactId>
  19. <version>4.13</version>
  20. <scope>test</scope>
  21. </dependency>
  • sql脚本
  1. DROP TABLE IF EXISTS `employee`;
  2. CREATE TABLE `employee` (
  3. `id` int(11) NOT NULL AUTO_INCREMENT,
  4. `last_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  5. `gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  6. `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  7. PRIMARY KEY (`id`) USING BTREE
  8. ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
  • db.propreties
  1. jdbc.url=jdbc:mysql://192.168.134.100:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
  2. jdbc.driverClass=com.mysql.cj.jdbc.Driver
  3. jdbc.username=root
  4. jdbc.password=123456
  • log4j.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
  3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  4. <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
  5. <param name="Encoding" value="UTF-8" />
  6. <layout class="org.apache.log4j.PatternLayout">
  7. <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
  8. </layout>
  9. </appender>
  10. <logger name="java.sql">
  11. <level value="debug" />
  12. </logger>
  13. <logger name="org.apache.ibatis">
  14. <level value="info" />
  15. </logger>
  16. <root>
  17. <level value="debug" />
  18. <appender-ref ref="STDOUT" />
  19. </root>
  20. </log4j:configuration>
  • Employee.java
  1. package com.sunxiaping.domain;
  2. import org.apache.ibatis.type.Alias;
  3. @Alias("emp")
  4. public class Employee {
  5. private Integer id;
  6. private String lastName;
  7. private String email;
  8. private String gender;
  9. public Integer getId() {
  10. return id;
  11. }
  12. public void setId(Integer id) {
  13. this.id = id;
  14. }
  15. public String getLastName() {
  16. return lastName;
  17. }
  18. public void setLastName(String lastName) {
  19. this.lastName = lastName;
  20. }
  21. public String getEmail() {
  22. return email;
  23. }
  24. public void setEmail(String email) {
  25. this.email = email;
  26. }
  27. public String getGender() {
  28. return gender;
  29. }
  30. public void setGender(String gender) {
  31. this.gender = gender;
  32. }
  33. @Override
  34. public String toString() {
  35. return "Employee{" +
  36. "id=" + id +
  37. ", lastName='" + lastName + '\'' +
  38. ", email='" + email + '\'' +
  39. ", gender='" + gender + '\'' +
  40. '}';
  41. }
  42. }
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. public interface EmployeeMapper {
  3. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. </mapper>
  • mybatis-config.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <properties resource="db.properties"></properties>
  7. <settings>
  8. <!-- 开启自动驼峰命名规则映射 -->
  9. <setting name="mapUnderscoreToCamelCase" value="true"/>
  10. <!-- 开启对jdbcType的NULL的支持 -->
  11. <setting name="jdbcTypeForNull" value="NULL"/>
  12. <!-- 开启延迟加载 -->
  13. <setting name="lazyLoadingEnabled" value="true"/>
  14. <!-- 开启按需加载 -->
  15. <setting name="aggressiveLazyLoading" value="false"/>
  16. </settings>
  17. <environments default="development">
  18. <environment id="development">
  19. <transactionManager type="JDBC"/>
  20. <dataSource type="POOLED">
  21. <property name="driver" value="${jdbc.driverClass}"/>
  22. <property name="url" value="${jdbc.url}"/>
  23. <property name="username" value="${jdbc.username}"/>
  24. <property name="password" value="${jdbc.password}"/>
  25. </dataSource>
  26. </environment>
  27. </environments>
  28. <mappers>
  29. <package name="com.sunxiaping.mapper"/>
  30. </mappers>
  31. </configuration>

第三章:if 判断

  • 示例:
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import java.util.List;
  4. public interface EmployeeMapper {
  5. List<Employee> getEmpsByConditionIf(Employee employee);
  6. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <select id="getEmpsByConditionIf" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id as id,last_name as lastName,gender as gender,email as email
  8. FROM employee
  9. WHERE 1 = 1
  10. <!--
  11. test:条件判断表达式OGNL
  12. -->
  13. <if test="id != null">
  14. AND id = #{id,jdbcType=INTEGER}
  15. </if>
  16. <if test="lastName != null and lastName != ''">
  17. AND last_name LIKE #{lastName,jdbcType=VARCHAR}
  18. </if>
  19. <if test="gender != null and gender != ''">
  20. AND gender = #{gender,jdbcType=VARCHAR}
  21. </if>
  22. <if test="email != null and email != ''">
  23. AND email = #{email,jdbcType=VARCHAR}
  24. </if>
  25. </select>
  26. </mapper>
  • 测试:
  1. package com.sunxiaping;
  2. import com.sunxiaping.domain.Employee;
  3. import com.sunxiaping.mapper.EmployeeMapper;
  4. import org.apache.ibatis.io.Resources;
  5. import org.apache.ibatis.session.SqlSession;
  6. import org.apache.ibatis.session.SqlSessionFactory;
  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  8. import org.junit.After;
  9. import org.junit.Before;
  10. import org.junit.Test;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. import java.util.List;
  14. public class EmployeeTest {
  15. SqlSessionFactory sqlSessionFactory = null;
  16. SqlSession sqlSession = null;
  17. EmployeeMapper employeeMapper = null;
  18. @Before
  19. public void before() throws IOException {
  20. String resource = "mybatis-config.xml";
  21. InputStream inputStream = Resources.getResourceAsStream(resource);
  22. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  23. sqlSession = sqlSessionFactory.openSession(true);
  24. employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
  25. }
  26. @After
  27. public void after() {
  28. if (null != sqlSession) {
  29. sqlSession.close();
  30. }
  31. }
  32. @Test
  33. public void testFindById() {
  34. Employee example = new Employee();
  35. example.setId(1);
  36. example.setGender("男");
  37. List<Employee> employeeList = employeeMapper.getEmpsByConditionIf(example);
  38. System.out.println("employeeList = " + employeeList);
  39. }
  40. }

第四章:where 查询条件

  • 如果查询条件中有多个 AND 或 OR 语句,Mybatis 推荐使用 where 标签,其内部会自动将多余的 AND 或 OR 去掉。当然,where 标签强制类似 AND xxx=xxx ,AND xxx=xxx 的方式。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import java.util.List;
  4. public interface EmployeeMapper {
  5. List<Employee> getEmpsByConditionWhere(Employee employee);
  6. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <select id="getEmpsByConditionWhere" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id as id,last_name as lastName,gender as gender,email as email
  8. FROM employee
  9. <where>
  10. <if test="id != null">
  11. id = #{id,jdbcType=INTEGER}
  12. </if>
  13. <if test="lastName != null and lastName != ''">
  14. AND last_name LIKE #{lastName,jdbcType=VARCHAR}
  15. </if>
  16. <if test="gender != null and gender != ''">
  17. AND gender = #{gender,jdbcType=VARCHAR}
  18. </if>
  19. <if test="email != null and email != ''">
  20. AND email = #{email,jdbcType=VARCHAR}
  21. </if>
  22. </where>
  23. </select>
  24. </mapper>
  • 测试:
  1. package com.sunxiaping;
  2. import com.sunxiaping.domain.Employee;
  3. import com.sunxiaping.mapper.EmployeeMapper;
  4. import org.apache.ibatis.io.Resources;
  5. import org.apache.ibatis.session.SqlSession;
  6. import org.apache.ibatis.session.SqlSessionFactory;
  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  8. import org.junit.After;
  9. import org.junit.Before;
  10. import org.junit.Test;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. import java.util.List;
  14. public class EmployeeTest {
  15. SqlSessionFactory sqlSessionFactory = null;
  16. SqlSession sqlSession = null;
  17. EmployeeMapper employeeMapper = null;
  18. @Before
  19. public void before() throws IOException {
  20. String resource = "mybatis-config.xml";
  21. InputStream inputStream = Resources.getResourceAsStream(resource);
  22. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  23. sqlSession = sqlSessionFactory.openSession(true);
  24. employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
  25. }
  26. @After
  27. public void after() {
  28. if (null != sqlSession) {
  29. sqlSession.close();
  30. }
  31. }
  32. @Test
  33. public void testFindById() {
  34. Employee example = new Employee();
  35. example.setGender("男");
  36. List<Employee> employeeList = employeeMapper.getEmpsByConditionWhere(example);
  37. System.out.println("employeeList = " + employeeList);
  38. }
  39. }

第五章:trim 自定义字符串截取

  • 上面的 where 标签有限制,一旦使用了类似 xxx=xxx AND,xxx=xxx AND 的情况,where 标签就失效了,这个时候可以使用 trim 自定义字符串截取,当前,trim 标签也可以模拟出 where 标签的效果。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import java.util.List;
  4. public interface EmployeeMapper {
  5. List<Employee> getEmpsByConditionTrim(Employee employee);
  6. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <select id="getEmpsByConditionTrim" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id as id,last_name as lastName,gender as gender,email as email
  8. FROM employee
  9. <!--
  10. trim标签
  11. prefix:前缀,trim标签体中是整个字符串拼串后的结果,prefix就是给整个字符串加一个前缀
  12. prefixOverrides:前缀覆盖。去掉整个字符串前面多余的字符
  13. suffix:后缀,prefix就是给整个字符串加一个后缀
  14. suffixOverrides:后缀覆盖。去掉整个字符串后面多余的字符
  15. -->
  16. <trim prefix="WHERE" suffixOverrides="AND">
  17. <if test="id != null">
  18. id = #{id,jdbcType=INTEGER} AND
  19. </if>
  20. <if test="lastName != null and lastName != ''">
  21. last_name LIKE #{lastName,jdbcType=VARCHAR} AND
  22. </if>
  23. <if test="gender != null and gender != ''">
  24. gender = #{gender,jdbcType=VARCHAR} AND
  25. </if>
  26. <if test="email != null and email != ''">
  27. email = #{email,jdbcType=VARCHAR}
  28. </if>
  29. </trim>
  30. </select>
  31. </mapper>
  • 测试:
  1. package com.sunxiaping;
  2. import com.sunxiaping.domain.Employee;
  3. import com.sunxiaping.mapper.EmployeeMapper;
  4. import org.apache.ibatis.io.Resources;
  5. import org.apache.ibatis.session.SqlSession;
  6. import org.apache.ibatis.session.SqlSessionFactory;
  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  8. import org.junit.After;
  9. import org.junit.Before;
  10. import org.junit.Test;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. import java.util.List;
  14. public class EmployeeTest {
  15. SqlSessionFactory sqlSessionFactory = null;
  16. SqlSession sqlSession = null;
  17. EmployeeMapper employeeMapper = null;
  18. @Before
  19. public void before() throws IOException {
  20. String resource = "mybatis-config.xml";
  21. InputStream inputStream = Resources.getResourceAsStream(resource);
  22. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  23. sqlSession = sqlSessionFactory.openSession(true);
  24. employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
  25. }
  26. @After
  27. public void after() {
  28. if (null != sqlSession) {
  29. sqlSession.close();
  30. }
  31. }
  32. @Test
  33. public void testFindById() {
  34. Employee example = new Employee();
  35. example.setGender("男");
  36. List<Employee> employeeList = employeeMapper.getEmpsByConditionTrim(example);
  37. System.out.println("employeeList = " + employeeList);
  38. }
  39. }

第六章:choose 分支选择

  • 有点类似 Java 中的 switch-case 语句。

  • 示例:如果查询条件中有 id ,就用 id 查询;如果查询条件中有 lastName ,就用 lastName 查询;如果查询条件中有 gender,就用 gener 查询;否则,用 emial 查询。

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import java.util.List;
  4. public interface EmployeeMapper {
  5. List<Employee> getEmpsByConditionChoose(Employee employee);
  6. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <select id="getEmpsByConditionChoose" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id as id,last_name as lastName,gender as gender,email as email
  8. FROM employee
  9. <where>
  10. <!--
  11. choose标签:分支选择,有点类似Java中的switch-case
  12. -->
  13. <choose>
  14. <when test="id != null">
  15. id = #{id,jdbcType=INTEGER}
  16. </when>
  17. <when test="lastName != null and lastName != ''">
  18. last_name = #{lastName,jdbcType=VARCHAR}
  19. </when>
  20. <when test="gender != null and gender != ''">
  21. gender = #{gender,jdbcType=VARCHAR}
  22. </when>
  23. <otherwise>
  24. email = #{email,jdbcType=VARCHAR}
  25. </otherwise>
  26. </choose>
  27. </where>
  28. </select>
  29. </mapper>

第七章:set 更新

  • set 标签一般结合 if 标签实现动态更新。Mybatis 中的 set 标签会自动将最右边多出的 , 去掉。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. void updateEmployee(Employee employee);
  5. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <update id="updateEmployee">
  7. UPDATE employee
  8. <set>
  9. <if test="lastName != null and lastName != ''">
  10. last_name = #{lastName,jdbcType=VARCHAR},
  11. </if>
  12. <if test="gender != null and gender != ''">
  13. gender = #{gender,jdbcType=VARCHAR},
  14. </if>
  15. <if test="email != null and email != ''">
  16. email = #{email,jdbcType=VARCHAR}
  17. </if>
  18. </set>
  19. <where>
  20. <if test="id != null">
  21. id = #{id,jdbcType=INTEGER}
  22. </if>
  23. </where>
  24. </update>
  25. </mapper>

第八章:foreach 遍历

  • foreach 标签类似于 jstl 中的 <c:forEach> 标签,都是迭代一个集合中的对象。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import org.apache.ibatis.annotations.Param;
  4. import java.util.List;
  5. public interface EmployeeMapper {
  6. List<Employee> findEmpsByConditionForeach(@Param("ids") List<Integer> ids);
  7. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <select id="findEmpsByConditionForeach" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id as id,last_name as lastName,gender as gender,email as email
  8. FROM employee
  9. <!--
  10. foreach 遍历集合
  11. collection:指定要遍历的集合
  12. item:将当前遍历的元素赋值给指定的变量
  13. separator:每个元素之间的分隔符
  14. open:遍历出所有的结果拼接一个开始的字符
  15. close:遍历出所有的结果拼接一个结束的字符
  16. index:
  17. 如果遍历的是List,那么index就是索引,item就是当前的值。
  18. 如果遍历的是Map,那么index就是Map的key,item就是Map中的值。
  19. -->
  20. <foreach collection="ids" item="id" open="WHERE id IN (" separator="," close=")">
  21. #{id,jdbcType=INTEGER}
  22. </foreach>
  23. </select>
  24. </mapper>

第九章:MySQL 下的 foreach 批量插入的两种方式

  • 第一种批量插入数据的 SQL 方式如下:
  1. INSERT INTO 表名(字段1,字段2,...) VALUES (值1,值2,...),(值1,值2,...);
  • 示例:
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import org.apache.ibatis.annotations.Param;
  4. import java.util.List;
  5. public interface EmployeeMapper {
  6. void batchInsertEmps(@Param("emps") List<Employee> employees);
  7. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <insert id="batchInsertEmps">
  7. <foreach collection="emps" item="emp" open="INSERT INTO employee (last_name,gender,email) VALUES" separator=",">
  8. (#{emp.lastName,jdbcType=VARCHAR},#{emp.gender,jdbcType=VARCHAR},#{emp.email,jdbcType=VARCHAR})
  9. </foreach>
  10. </insert>
  11. </mapper>
  • 第二种批量插入数据的 SQL 方式如下:
  1. INSERT INTO 表名(字段1,字段2,...) VALUES (值1,值2,...);
  2. INSERT INTO 表名(字段1,字段2,...) VALUES (值1,值2,...);
  • 但是,在 JDBC 操纵 MySQL 的时候,需要在 jdbc.url 上加上“allowMultiQueries=true”参数,当然这个参数也可以用于批量删除、批量更新。

  • 示例:

  • db.properties
  1. jdbc.url=jdbc:mysql://192.168.134.100:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true
  2. jdbc.driverClass=com.mysql.cj.jdbc.Driver
  3. jdbc.username=root
  4. jdbc.password=123456
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import org.apache.ibatis.annotations.Param;
  4. import java.util.List;
  5. public interface EmployeeMapper {
  6. void batchInsertEmps(@Param("emps") List<Employee> employees);
  7. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <insert id="batchInsertEmps">
  7. <foreach collection="emps" item="emp" separator=";">
  8. INSERT INTO employee (last_name,gender,email) VALUES (#{emp.lastName,jdbcType=VARCHAR},#{emp.gender,jdbcType=VARCHAR},#{emp.email,jdbcType=VARCHAR})
  9. </foreach>
  10. </insert>
  11. </mapper>

第十章:Oracle 下的 foreach 批量插入的两种方式

  • 第一种批量插入数据的 SQL 方式如下:
  1. begin
  2. INSERT INTO 表名(字段1,字段2,...) VALUES (值1,值2,...);
  3. INSERT INTO 表名(字段1,字段2,...) VALUES (值1,值2,...);
  4. end;
  • 示例:
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import org.apache.ibatis.annotations.Param;
  4. import java.util.List;
  5. public interface EmployeeMapper {
  6. void batchInsertEmps(@Param("emps") List<Employee> employees);
  7. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <insert id="batchInsertEmps">
  7. <foreach collection="emps" item="emp" open="begin" close="end;" >
  8. INSERT INTO employee (id,last_name,gender,email) VALUES (#{employee_seq.nextval},#{emp.lastName,jdbcType=VARCHAR},#{emp.gender,jdbcType=VARCHAR},#{emp.email,jdbcType=VARCHAR});
  9. </foreach>
  10. </insert>
  11. </mapper>
  • 第二种批量插入数据的 SQL 方式如下:
  1. INSERT INTO 表名(字段1,字段2,...)
  2. SELECT 别名1,别名2,... FROM (
  3. SELECT 1 别名1,值2 别名2,... FROM dual
  4. UNION
  5. SELECT 1 别名1,值2 别名2<?xml version="1.0" encoding="UTF-8" ?>
  6. <!DOCTYPE mapper
  7. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  8. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  9. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  10. <insert id="batchInsertEmps">
  11. <foreach collection="emps" item="emp" open="INSERT INTO employee (id,last_name,gender,email) SELECT employee.nextval,lastName,gender,email FROM (" close=")" separator="UNION">
  12. SELECT #{emp.lastName,jdbcType=VARCHAR} lastName,#{emp.gender,jdbcType=VARCHAR} gender,#{emp.email,jdbcType=VARCHAR} email FROM dual
  13. </foreach>
  14. </insert>
  15. </mapper>,... FROM dual
  16. )
  • 示例:
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import org.apache.ibatis.annotations.Param;
  4. import java.util.List;
  5. public interface EmployeeMapper {
  6. void batchInsertEmps(@Param("emps") List<Employee> employees);
  7. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <insert id="batchInsertEmps">
  7. <foreach collection="emps" item="emp" open="INSERT INTO employee (id,last_name,gender,email) SELECT employee.nextval,lastName,gender,email FROM (" close=")" separator="UNION">
  8. SELECT #{emp.lastName,jdbcType=VARCHAR} lastName,#{emp.gender,jdbcType=VARCHAR} gender,#{emp.email,jdbcType=VARCHAR} email FROM dual
  9. </foreach>
  10. </insert>
  11. </mapper>

第十一章:内置参数

  • Mybatis 不只是方法传递过来的参数可以用来判断,取值,Mybatis默认还有两个默认的参数:_parameter_databaseId
  • _parameter:代表整个参数。
    • 如果是单个参数:_parameter 就是这个参数。
    • 如果是多个参数:参数会封装到一个 Map 中,_parameter 就是代表这个 Map 。
  • _databaseId:如果在全局配置文件中配置了 databaseIdProvider 标签,那么 _databaseId 就是代表当前数据库的别名。

  • 示例:

  • mybatis-config.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <properties resource="db.properties"></properties>
  7. <settings>
  8. <!-- 开启自动驼峰命名规则映射 -->
  9. <setting name="mapUnderscoreToCamelCase" value="true"/>
  10. <!-- 开启对jdbcTypeNULL的支持 -->
  11. <setting name="jdbcTypeForNull" value="NULL"/>
  12. <!-- 开启延迟加载 -->
  13. <setting name="lazyLoadingEnabled" value="true"/>
  14. <!-- 开启按需加载 -->
  15. <setting name="aggressiveLazyLoading" value="false"/>
  16. </settings>
  17. <environments default="development">
  18. <environment id="development">
  19. <transactionManager type="JDBC"/>
  20. <dataSource type="POOLED">
  21. <property name="driver" value="${jdbc.driverClass}"/>
  22. <property name="url" value="${jdbc.url}"/>
  23. <property name="username" value="${jdbc.username}"/>
  24. <property name="password" value="${jdbc.password}"/>
  25. </dataSource>
  26. </environment>
  27. </environments>
  28. <databaseIdProvider type="DB_VENDOR">
  29. <!--
  30. 为不同的数据库厂商起别名
  31. -->
  32. <property name="MySQL" value="mysql"/>
  33. <property name="Oracle" value="oracle"/>
  34. <property name="SQL Server" value="sqlserver"/>
  35. </databaseIdProvider>
  36. <mappers>
  37. <package name="com.sunxiaping.mapper"/>
  38. </mappers>
  39. </configuration>
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import java.util.List;
  4. public interface EmployeeMapper {
  5. List<Employee> findByBuiltParameter();
  6. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <select id="findByBuiltParameter" resultType="com.sunxiaping.domain.Employee">
  7. <if test="_databaseId == 'mysql'">
  8. SELECT id as id,last_name as lastName,email as email ,gender as gender
  9. FROM employee
  10. LIMIT 0,5
  11. </if>
  12. <if test="_databaseId == 'oracle'">
  13. SELECT * FROM
  14. (SELECT e.*,rownum as r1 FROM employee e WHERE rownum &lt; 5)
  15. WHERE r1 &gt; 1
  16. </if>
  17. </select>
  18. </mapper>

第十二章:bind 绑定

  • bind 标签可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import org.apache.ibatis.annotations.Param;
  4. import java.util.List;
  5. public interface EmployeeMapper {
  6. List<Employee> findByLastNameLike(@Param("lastName") String lastName);
  7. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <select id="findByLastNameLike" resultType="com.sunxiaping.domain.Employee">
  7. <bind name="_lastName" value="'%' + lastName + '%'"></bind>
  8. SELECT id as id,last_name as lastName,email as email ,gender as gender
  9. FROM employee
  10. WHERE last_name like #{_lastName,jdbcType=VARCHAR}
  11. </select>
  12. </mapper>
  • 测试:
  1. package com.sunxiaping;
  2. import com.sunxiaping.domain.Employee;
  3. import com.sunxiaping.mapper.EmployeeMapper;
  4. import org.apache.ibatis.io.Resources;
  5. import org.apache.ibatis.session.SqlSession;
  6. import org.apache.ibatis.session.SqlSessionFactory;
  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  8. import org.junit.After;
  9. import org.junit.Before;
  10. import org.junit.Test;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. import java.util.List;
  14. public class EmployeeTest {
  15. SqlSessionFactory sqlSessionFactory = null;
  16. SqlSession sqlSession = null;
  17. EmployeeMapper employeeMapper = null;
  18. @Before
  19. public void before() throws IOException {
  20. String resource = "mybatis-config.xml";
  21. InputStream inputStream = Resources.getResourceAsStream(resource);
  22. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  23. sqlSession = sqlSessionFactory.openSession(true);
  24. employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
  25. }
  26. @After
  27. public void after() {
  28. if (null != sqlSession) {
  29. sqlSession.close();
  30. }
  31. }
  32. @Test
  33. public void testFindById() {
  34. List<Employee> employeeList = employeeMapper.findByLastNameLike("a");
  35. System.out.println("employeeList = " + employeeList);
  36. }
  37. }

第十三章:抽取可重用的 SQL 片段

  • sql 标签可以抽取可重用的 SQL 片段,方便后面引用。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import org.apache.ibatis.annotations.Param;
  4. import java.util.List;
  5. public interface EmployeeMapper {
  6. List<Employee> findByLastNameLike(@Param("lastName") String lastName);
  7. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <!--
  7. 抽取可重用的SQL片段,方便后面引用
  8. -->
  9. <sql id="emp_sql" >
  10. id as id,last_name as lastName,email as email ,gender as gender
  11. </sql>
  12. <select id="findByLastNameLike" resultType="com.sunxiaping.domain.Employee">
  13. <bind name="_lastName" value="'%' + lastName + '%'"></bind>
  14. <!--
  15. include标签,引用外部定义的可重用的SQL片段
  16. -->
  17. SELECT <include refid="emp_sql"/>
  18. FROM employee
  19. WHERE last_name like #{_lastName,jdbcType=VARCHAR}
  20. </select>
  21. </mapper>