第一章:增删改查

  • 示例:
  • 导入相关 jar 包的 Maven 坐标:
  1. <dependency>
  2. <groupId>org.mybatis</groupId>
  3. <artifactId>mybatis</artifactId>
  4. <version>3.5.5</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>
  • 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
  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 Employee() {
  10. }
  11. public Employee(Integer id, String lastName, String email, String gender) {
  12. this.id = id;
  13. this.lastName = lastName;
  14. this.email = email;
  15. this.gender = gender;
  16. }
  17. public Integer getId() {
  18. return id;
  19. }
  20. public void setId(Integer id) {
  21. this.id = id;
  22. }
  23. public String getLastName() {
  24. return lastName;
  25. }
  26. public void setLastName(String lastName) {
  27. this.lastName = lastName;
  28. }
  29. public String getEmail() {
  30. return email;
  31. }
  32. public void setEmail(String email) {
  33. this.email = email;
  34. }
  35. public String getGender() {
  36. return gender;
  37. }
  38. public void setGender(String gender) {
  39. this.gender = gender;
  40. }
  41. @Override
  42. public String toString() {
  43. return "Employee{" +
  44. "id=" + id +
  45. ", lastName='" + lastName + '\'' +
  46. ", email='" + email + '\'' +
  47. ", gender='" + gender + '\'' +
  48. '}';
  49. }
  50. }
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. /**
  5. * 根据id查询员工的信息
  6. *
  7. * @param id
  8. * @return
  9. */
  10. Employee findById(Integer id);
  11. /**
  12. * 增加员工信息
  13. *
  14. * @param employee
  15. */
  16. void addEmp(Employee employee);
  17. /**
  18. * 修改员工信息
  19. *
  20. * @param employee
  21. */
  22. void updateEmp(Employee employee);
  23. /**
  24. * 根据id删除员工信息
  25. *
  26. * @param id
  27. */
  28. void deleteEmpById(Integer id);
  29. }
  • 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="findById" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id,last_name as lastName,email,gender
  8. FROM employee
  9. WHERE id = #{id,jdbcType=INTEGER}
  10. </select>
  11. <insert id="addEmp">
  12. INSERT INTO employee (last_name,email,gender)
  13. VALUES (#{lastName,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{gender,jdbcType=VARCHAR})
  14. </insert>
  15. <update id="updateEmp">
  16. UPDATE employee
  17. SET last_name = #{lastName,jdbcType=VARCHAR},email = #{email,jdbcType=VARCHAR},gender=#{gender,jdbcType=VARCHAR}
  18. WHERE id = #{id,jdbcType=INTEGER}
  19. </update>
  20. <delete id="deleteEmpById">
  21. DELETE FROM employee
  22. WHERE id = #{id,jdbcType=INTEGER}
  23. </delete>
  24. </mapper>
  • mybatis-copnfig.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. </settings>
  11. <environments default="development">
  12. <environment id="development">
  13. <transactionManager type="JDBC"/>
  14. <dataSource type="POOLED">
  15. <!-- 使用${}引入db.properties属性文件中的内容 -->
  16. <property name="driver" value="${jdbc.driverClass}"/>
  17. <property name="url" value="${jdbc.url}"/>
  18. <property name="username" value="${jdbc.username}"/>
  19. <property name="password" value="${jdbc.password}"/>
  20. </dataSource>
  21. </environment>
  22. </environments>
  23. <mappers>
  24. <package name="com.sunxiaping.mapper"/>
  25. </mappers>
  26. </configuration>
  • 测试:
  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. public class EmployeeTest {
  14. SqlSessionFactory sqlSessionFactory = null;
  15. SqlSession sqlSession = null;
  16. EmployeeMapper employeeMapper = null;
  17. @Before
  18. public void before() throws IOException {
  19. String resource = "mybatis-config.xml";
  20. InputStream inputStream = Resources.getResourceAsStream(resource);
  21. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  22. sqlSession = sqlSessionFactory.openSession(true);
  23. employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
  24. }
  25. @After
  26. public void after() {
  27. if (null != sqlSession) {
  28. sqlSession.close();
  29. }
  30. }
  31. @Test
  32. public void testFindById() {
  33. Employee employee = employeeMapper.findById(1);
  34. System.out.println("employee = " + employee);
  35. }
  36. @Test
  37. public void testAddEmp() {
  38. Employee employee = new Employee();
  39. employee.setEmail("jerry@qq.com");
  40. employee.setGender("男");
  41. employee.setLastName("jerry");
  42. employeeMapper.addEmp(employee);
  43. }
  44. @Test
  45. public void testUpdateEmp(){
  46. Employee employee = employeeMapper.findById(2);
  47. employee.setGender("女");
  48. employeeMapper.updateEmp(employee);
  49. }
  50. @Test
  51. public void testDeleteEmpById(){
  52. employeeMapper.deleteEmpById(2);
  53. }
  54. }

第二章:INSERT 获取自增主键的值

  • MySQL 等数据库支持自增主键,自增主键的值是通过 statement.getGenerateKeys() 方法获取的。
  • 通过使用 useGeneratedKeys="true" 开启自增主键获取主键值的策略。
  • 通过使用 keyProperty="id" 指定对应的主键属性,Mybatis 获取主键值以后,将这个值封装给 JavaBean 的哪个属性。

  • 示例:

  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. MySQL支持自增主键,自增主键值的获取,Mybatis是利用statement.getGeneratedKeys()
  8. useGeneratedKeys="true":使用自增主键获取主键值策略
  9. keyProperty="id":指定对应的主键属性,Mybatis获取主键值以后,将这个值封装给JavaBean的哪个属性
  10. -->
  11. <insert id="addEmp" useGeneratedKeys="true" keyProperty="id" parameterType="com.sunxiaping.domain.Employee">
  12. INSERT INTO employee (last_name,email,gender)
  13. VALUES (#{lastName,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{gender,jdbcType=VARCHAR})
  14. </insert>
  15. </mapper>

第三章:INSERT 获取非自增主键的值

  • Oracle 不支持自增主键,Oracle 是使用序列来模拟自增的。
  • 每次插入的数据的主键都是从序列中拿到的值。

  • 示例:

  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. Oracle不支持自增主键,Oracle是使用序列来模拟自增的。
  8. 每次插入的数据的主键都是从序列中拿到的值。
  9. -->
  10. <insert id="addEmp" useGeneratedKeys="true" keyProperty="id" parameterType="com.sunxiaping.domain.Employee">
  11. <!--
  12. 插入时的主键是从序列中拿到的
  13. keyProperty:查询的主键封装给JavaBean的哪个属性
  14. order:
  15. - BEFORE:当前的SQL在插入SQL之前运行
  16. - 运行顺序:先运行selectKey中的SQL语句,查询出id,然后将id封装给JavaBean中的id属性,在运行插入SQL的时候,就可以取出id属性对应的值
  17. - AFTER: 先运行插入SQL,再运行当前的SQL
  18. - 运行顺序:先运行插入的SQL(会从序列中取出新值作为id),再运行selectKey查询id,然后将id封装给JavaBean的id属性,并发情况下可能有问题。
  19. resultType:查出的数据的返回值类型
  20. -->
  21. <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Integer">
  22. <!--
  23. 编写查询主键的SQL语句
  24. -->
  25. SELECT employee_seq.nextval FROM dual
  26. </selectKey>
  27. INSERT INTO employee (id,last_name,email,gender)
  28. VALUES (#{id,jdbcType=INTEGER},#{lastName,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{gender,jdbcType=VARCHAR})
  29. </insert>
  30. </mapper>
  • 示例:
  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. Oracle不支持自增主键,Oracle是使用序列来模拟自增的。
  8. 每次插入的数据的主键都是从序列中拿到的值。
  9. -->
  10. <insert id="addEmp" useGeneratedKeys="true" keyProperty="id" parameterType="com.sunxiaping.domain.Employee">
  11. <!--
  12. 插入时的主键是从序列中拿到的
  13. keyProperty:查询的主键封装给JavaBean的哪个属性
  14. order:
  15. - BEFORE:当前的SQL在插入SQL之前运行
  16. - 运行顺序:先运行selectKey中的SQL语句,查询出id,然后将id封装给JavaBean中的id属性,在运行插入SQL的时候,就可以取出id属性对应的值
  17. - AFTER: 先运行插入SQL,再运行当前的SQL
  18. - 运行顺序:先运行插入的SQL(会从序列中取出新值作为id),再运行selectKey查询id,然后将id封装给JavaBean的id属性,并发情况下可能有问题。
  19. resultType:查出的数据的返回值类型
  20. -->
  21. <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
  22. <!--
  23. 编写查询主键的SQL语句
  24. -->
  25. SELECT employee_seq.currval FROM dual
  26. </selectKey>
  27. INSERT INTO employee (id,last_name,email,gender)
  28. VALUES (employee_seq.nextval},#{lastName,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{gender,jdbcType=VARCHAR})
  29. </insert>
  30. </mapper>

第四章:参数处理

4.1 单个参数

  • Mybatis 不需要经过任何处理,Mybatis 可以直接使用 #{参数名} 取出参数值。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. /**
  5. * 根据id查询员工的信息
  6. *
  7. * @param id
  8. * @return
  9. */
  10. Employee findById(Integer id);
  11. }
  • 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="findById" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id,last_name as lastName,email,gender
  8. FROM employee
  9. WHERE id = #{abc,jdbcType=INTEGER}
  10. </select>
  11. </mapper>

4.2 多个参数

  • 任意多个参数,都会被 Mybatis 重新包装成一个 Map 传入。Map 中的 key 就是 param1, param2 ,…,value 是传入的参数值。
  • #{} 就是从 map 中获取指定的 key 的值。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. /**
  5. * 根据id和lastName查询员工信息
  6. *
  7. * @param id
  8. * @param lastName
  9. * @return
  10. */
  11. Employee findByIdAndLastName(Integer id, String lastName);
  12. }
  • 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="findByIdAndLastName" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id,last_name as lastName,email,gender
  8. FROM employee
  9. WHERE id = #{param1,jdbcType=INTEGER} AND last_name = #{param2,jdbcType=VARCHAR}
  10. </select>
  11. </mapper>

4.3 命名参数

  • 当多个参数的时候,可以使用 @Param 注解明确指定 Mybatis 中传入参数 Map 中的 key ,Map 中的 key 就是使用 @Param 注解指定的值,value 就是传入的参数值。
  • #{指定的key} 就可以取出对应的参数值。

  • 示例:

  • Employee.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import org.apache.ibatis.annotations.Param;
  4. public interface EmployeeMapper {
  5. /**
  6. * 根据id和lastName查询员工信息
  7. *
  8. * @param id
  9. * @param lastName
  10. * @return
  11. */
  12. Employee findByIdAndLastName(@Param("id") Integer id,@Param("lastName") String lastName);
  13. }
  • 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="findByIdAndLastName" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id,last_name as lastName,email,gender
  8. FROM employee
  9. WHERE id = #{id,jdbcType=INTEGER} AND last_name = #{lastName,jdbcType=VARCHAR}
  10. </select>
  11. </mapper>

4.4 POJO

  • 如果多个参数正好是业务逻辑的数据模型,我们就可以直接传入 POJO 。#{属性名} 取出传入 POJO 的属性值。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. Employee findByPOJO(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. <select id="findByPOJO" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id,last_name as lastName,email,gender
  8. FROM employee
  9. WHERE id = #{id,jdbcType=INTEGER} AND last_name = #{lastName,jdbcType=VARCHAR}
  10. </select>
  11. </mapper>

4.5 Map

  • 如果多个参数不是业务模型的数据,没有对应的 POJO ,不经常使用,为了方便,我们可以传入 Map 。
  • #{key} 取出传入 map 中对应的值。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import java.util.Map;
  4. public interface EmployeeMapper {
  5. Employee findByMap(Map<String, Object> map);
  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="findByMap" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id,last_name as lastName,email,gender
  8. FROM employee
  9. WHERE id = #{id,jdbcType=INTEGER} AND last_name = #{lastName,jdbcType=VARCHAR}
  10. </select>
  11. </mapper>

4.6 TO

  • 如果多个参数不是业务模型中的数据,但是经常使用,推荐编写一个 TO(Transfer Object)数据传输对象。

  • 示例:

  • Page.java
  1. package com.sunxiaping.to;
  2. /**
  3. * 分页的参数
  4. */
  5. public class Page {
  6. /**
  7. * 每页显示条数
  8. */
  9. private Integer pageSize;
  10. /**
  11. * 起始页码
  12. */
  13. private Integer pageNum;
  14. public Integer getPageSize() {
  15. return pageSize;
  16. }
  17. public void setPageSize(Integer pageSize) {
  18. this.pageSize = pageSize;
  19. }
  20. public Integer getPageNum() {
  21. return pageNum;
  22. }
  23. public void setPageNum(Integer pageNum) {
  24. this.pageNum = pageNum;
  25. }
  26. @Override
  27. public String toString() {
  28. return "Page{" +
  29. "pageSize=" + pageSize +
  30. ", pageNum=" + pageNum +
  31. '}';
  32. }
  33. }
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import com.sunxiaping.to.Page;
  4. import java.util.List;
  5. public interface EmployeeMapper {
  6. List<Employee> findByPage(Page page);
  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="findByPage" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id,last_name as lastName,email,gender
  8. FROM employee
  9. LIMIT #{pageNum},#{pageSize}
  10. </select>
  11. </mapper>

4.7 Collection 类型(List类型、Set类型)数组类型

  • 如果传入的参数是 Collection 类型(List 类型、Set 类型)或数组类型,那么 Mybatis 会针对这些类型进行特殊处理:如果是 Collection 类型,那么 Mybatis 内部封装参数的 Map 的 key 就是 collection ;如果是 List 类型,那么 Mybatis 内部封装参数的 Map 的 key 可以是 list ;而如果是数组类型, Mybatis 内部封装参数的 Map 的 key 是 array 。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import java.util.List;
  4. import java.util.Set;
  5. public interface EmployeeMapper {
  6. List<Employee> findBySet(Set<Integer> id);
  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="findBySet" resultType="com.sunxiaping.domain.Employee">
  7. SELECT id,last_name as lastName,email,gender
  8. FROM employee
  9. WHERE id = #{collection}
  10. </select>
  11. </mapper>

4.8 # 和 $ 取值区别

  • #{} 获取参数的值,预编译到 SQL 中,安全。
  • ${} 获取参数的值,拼接到 SQL 中,有 SQL 注入问题。
  • 注意:
  • 大多数情况下,我们取参数的值的时候使用 #{}
  • 原生 JDBC 不支持占位符的地方,我们就可以使用 ${}
    • 比如:排序
    • 比如:财务系统在设计之初按照年份分表,查询的时候应该这样写:
  1. Order BY ${name}
  1. SELECT * FROM ${year}_salary WHERE xxx;
  • 示例:
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import java.util.Map;
  4. public interface EmployeeMapper {
  5. Employee findByMap(Map<String,Object> map);
  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="findByMap" resultType="com.sunxiaping.domain.Employee" parameterType="java.util.Map">
  7. SELECT id,last_name as lastName,email,gender
  8. FROM ${tableName}
  9. WHERE id = #{id}
  10. </select>
  11. </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.HashMap;
  14. import java.util.Map;
  15. public class EmployeeTest {
  16. SqlSessionFactory sqlSessionFactory = null;
  17. SqlSession sqlSession = null;
  18. EmployeeMapper employeeMapper = null;
  19. @Before
  20. public void before() throws IOException {
  21. String resource = "mybatis-config.xml";
  22. InputStream inputStream = Resources.getResourceAsStream(resource);
  23. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  24. sqlSession = sqlSessionFactory.openSession(true);
  25. employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
  26. }
  27. @After
  28. public void after() {
  29. if (null != sqlSession) {
  30. sqlSession.close();
  31. }
  32. }
  33. @Test
  34. public void testFindById() {
  35. Map<String, Object> map = new HashMap<>();
  36. map.put("id",1);
  37. map.put("tableName","employee");
  38. Employee employee = employeeMapper.findByMap(map);
  39. System.out.println("employee = " + employee);
  40. }
  41. }

4.9 #取值时指定参数的相关规则

  • Mybatis 在参数位置支持如下的属性:
    • javaType
    • jdbcType
    • mode(用于存储过程)
    • numericScale
    • resultMap
    • typeHandler
    • jdbcTypeName
    • expression
  • 在某种特定的条件下,jdbcType 通常需要被设置。

    • 在我们的数据为 null 的时候,有些数据库可能不能识别 Mybatis 对 null 的默认处理,比如 Oracle 。
    • Mybatis对 null 的默认处理时的 jdbcType 是 OTHER ,这种类型 MySQL 能正确识别,但是 Oracle 不能。
      • ① 我们在使用 Oracle 保存 null 的时候,需要设置 jdbcType 为 NULL 。
      • ② 在全局配置文件 mybatis-config.xml 中设置 jdbcTypeForNull 的值是 NULL(推荐这种,Oracle 和 MySQL 都支持)。
  • 示例:修改 Mybatis 对 Oracle 的 NULL 值的默认处理

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. int addEmp(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. <insert id="addEmp" useGeneratedKeys="true" keyProperty="id" parameterType="com.sunxiaping.domain.Employee">
  7. <selectKey>
  8. SELECT employee_seq.nextval FROM dual
  9. </selectKey>
  10. INSERT INTO employee (id,last_name,email,gender)
  11. <!--
  12. 在Oracle数据库中,如果是null值,需要设置jdbcType=NULL
  13. -->
  14. VALUES (#{id,jdbcType=INTEGER},#{lastName,jdbcType=VARCHAR},#{email,jdbcType=NULL},#{gender,jdbcType=VARCHAR})
  15. </insert>
  16. </mapper>

第五章:select 元素

5.1 概述

  • select 元素用于定义查询操作。
  • id:唯一标识符。用来引用这条语句,需要和接口的方法名一致。
  • parameterType:参数类型。可以不传,Mybatis 会根据 TypeHandler 自动推断。
  • resultType:返回值类型。别名或者全类名,如果返回的是集合,定义集合中元素的类型。不能和 resultMap 同时使用。
  • resultMap:实现高级结果集映射。不能和 resultType 一起使用。

5.2 resultType

5.2.1 返回 List

  • 对于 resultType 来说,如果返回的是一个集合,需要写集合中的类型。

  • 示例:

  • 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> findByGender(String gender);
  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. <!--
  7. resultType:如果返回的是一个集合,需要写集合里面的类型
  8. -->
  9. <select id="findByGender" resultType="com.sunxiaping.domain.Employee">
  10. SELECT * FROM employee
  11. WHERE gender = #{gender,jdbcType=VARCHAR}
  12. </select>
  13. </mapper>

5.2.2 返回 Map

  • 返回一条记录封装 Map ,key 就是列名,值就是对应的值。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import java.util.Map;
  3. public interface EmployeeMapper {
  4. Map<String, Object> findById(Integer id);
  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. <select id="findById" resultType="java.util.Map">
  7. SELECT * FROM employee
  8. WHERE id = #{id,jdbcType=INTEGER}
  9. </select>
  10. </mapper>
  • 返回多条记录将其封装为 Map<主键类型,对象类型>,key 是这条记录的主键,值是这条记录。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. import org.apache.ibatis.annotations.MapKey;
  4. import java.util.Map;
  5. public interface EmployeeMapper {
  6. @MapKey("id")
  7. Map<Integer, Employee> findById(Integer id);
  8. }
  • 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="findById" resultType="java.util.Map">
  7. SELECT id,last_name as lastName,gender,email FROM employee
  8. WHERE id = #{id,jdbcType=INTEGER}
  9. </select>
  10. </mapper>

5.3 resultMap

5.3.1 自定义结果映射规则

  • 示例:
  • EmplyeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. Employee findById(Integer id);
  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. <!--
  7. resultMap 自定义关系结果映射规则
  8. id:唯一方便引用的id
  9. type:自定义规则的JavaBean类型
  10. -->
  11. <resultMap id="emp" type="com.sunxiaping.domain.Employee">
  12. <!--
  13. id:指定主键列的封装规则
  14. column:指定哪一列
  15. property:指定column对应的JavaBean属性
  16. -->
  17. <id property="id" column="id"/>
  18. <!--
  19. result:定义普通列的封装规则
  20. column:指定哪一列
  21. property:指定column对应的JavaBean属性
  22. -->
  23. <result property="lastName" column="last_name"/>
  24. <!-- 其它不指定的列会自动封装 -->
  25. <result property="email" column="email"/>
  26. <result property="gender" column="gender"/>
  27. </resultMap>
  28. <select id="findById" resultMap="emp">
  29. SELECT * FROM employee
  30. WHERE id = #{id,jdbcType=INTEGER}
  31. </select>
  32. </mapper>

5.3.2 关联查询

5.3.2.1 环境搭建

  • SQL 脚本:
  1. DROP TABLE IF EXISTS `department`;
  2. CREATE TABLE `department` (
  3. `id` int(11) NOT NULL AUTO_INCREMENT,
  4. `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  5. PRIMARY KEY (`id`) USING BTREE
  6. ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
  7. INSERT INTO `department` VALUES (1, '开发部');
  8. INSERT INTO `department` VALUES (2, '测试部');
  9. DROP TABLE IF EXISTS `employee`;
  10. CREATE TABLE `employee` (
  11. `id` int(11) NOT NULL AUTO_INCREMENT,
  12. `last_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  13. `gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  14. `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  15. `department_id` int(11) NULL DEFAULT NULL,
  16. PRIMARY KEY (`id`) USING BTREE,
  17. INDEX `fk_department_id`(`department_id`) USING BTREE,
  18. CONSTRAINT `fk_department_id` FOREIGN KEY (`department_id`) REFERENCES `department` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
  19. ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
  20. INSERT INTO `employee` VALUES (1, 'tom', '男', 'tom@qq.com', 1);
  21. INSERT INTO `employee` VALUES (2, 'aa', '女', NULL, 2);

5.3.2.2 级联属性封装查询结果

  • 示例:查询一个员工信息以及其所在部门信息
  • Department.java
  1. package com.sunxiaping.domain;
  2. public class Department {
  3. private Integer id;
  4. private String name;
  5. public Integer getId() {
  6. return id;
  7. }
  8. public void setId(Integer id) {
  9. this.id = id;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. @Override
  18. public String toString() {
  19. return "Department{" +
  20. "id=" + id +
  21. ", name='" + name + '\'' +
  22. '}';
  23. }
  24. }
  • 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. private Department department;
  10. public Integer getId() {
  11. return id;
  12. }
  13. public void setId(Integer id) {
  14. this.id = id;
  15. }
  16. public String getLastName() {
  17. return lastName;
  18. }
  19. public void setLastName(String lastName) {
  20. this.lastName = lastName;
  21. }
  22. public String getEmail() {
  23. return email;
  24. }
  25. public void setEmail(String email) {
  26. this.email = email;
  27. }
  28. public String getGender() {
  29. return gender;
  30. }
  31. public void setGender(String gender) {
  32. this.gender = gender;
  33. }
  34. @Override
  35. public String toString() {
  36. return "Employee{" +
  37. "id=" + id +
  38. ", lastName='" + lastName + '\'' +
  39. ", email='" + email + '\'' +
  40. ", gender='" + gender + '\'' +
  41. ", department=" + department +
  42. '}';
  43. }
  44. }
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. Employee findEmpAndDeptById(Integer id);
  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. <resultMap id="emp" type="com.sunxiaping.domain.Employee">
  7. <id property="id" column="id"/>
  8. <result property="lastName" column="last_name"/>
  9. <result property="email" column="email"/>
  10. <result property="gender" column="gender"/>
  11. <result property="department.id" column="did"/>
  12. <result property="department.name" column="dept_name"/>
  13. </resultMap>
  14. <select id="findEmpAndDeptById" resultMap="emp">
  15. SELECT e.id as id,e.last_name as last_name,e.gender as gender,e.email as email,d.id as did,d.name as dept_name
  16. FROM employee e INNER JOIN department d
  17. ON e.department_id = d.id
  18. WHERE e.id = #{id,jdbcType=INTEGER}
  19. </select>
  20. </mapper>

5.3.2.3 association 定义关联对象

  • 示例:查询一个员工信息以及其所在部门信息
  • Department.java
  1. package com.sunxiaping.domain;
  2. public class Department {
  3. private Integer id;
  4. private String name;
  5. public Integer getId() {
  6. return id;
  7. }
  8. public void setId(Integer id) {
  9. this.id = id;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. @Override
  18. public String toString() {
  19. return "Department{" +
  20. "id=" + id +
  21. ", name='" + name + '\'' +
  22. '}';
  23. }
  24. }
  • 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. private Department department;
  10. public Integer getId() {
  11. return id;
  12. }
  13. public void setId(Integer id) {
  14. this.id = id;
  15. }
  16. public String getLastName() {
  17. return lastName;
  18. }
  19. public void setLastName(String lastName) {
  20. this.lastName = lastName;
  21. }
  22. public String getEmail() {
  23. return email;
  24. }
  25. public void setEmail(String email) {
  26. this.email = email;
  27. }
  28. public String getGender() {
  29. return gender;
  30. }
  31. public void setGender(String gender) {
  32. this.gender = gender;
  33. }
  34. @Override
  35. public String toString() {
  36. return "Employee{" +
  37. "id=" + id +
  38. ", lastName='" + lastName + '\'' +
  39. ", email='" + email + '\'' +
  40. ", gender='" + gender + '\'' +
  41. ", department=" + department +
  42. '}';
  43. }
  44. }
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. Employee findEmpAndDeptById(Integer id);
  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. <resultMap id="emp" type="com.sunxiaping.domain.Employee">
  7. <id property="id" column="id"/>
  8. <result property="lastName" column="last_name"/>
  9. <result property="email" column="email"/>
  10. <result property="gender" column="gender"/>
  11. <!--
  12. association:可以指定联合的JavaBean对象
  13. property:指定哪个属性是联合的对象
  14. javaType:指定联合对象的类型
  15. -->
  16. <association property="department" javaType="com.sunxiaping.domain.Department">
  17. <id property="id" column="did"/>
  18. <id property="name" column="dept_name"/>
  19. </association>
  20. </resultMap>
  21. <select id="findEmpAndDeptById" resultMap="emp">
  22. SELECT e.id as id,e.last_name as last_name,e.gender as gender,e.email as email,d.id as did,d.name as dept_name
  23. FROM employee e INNER JOIN department d
  24. ON e.department_id = d.id
  25. WHERE e.id = #{id,jdbcType=INTEGER}
  26. </select>
  27. </mapper>

5.3.2.4 association 分步查询

  • 示例:查询一个员工信息以及其所在部门信息
  • Department.java
  1. package com.sunxiaping.domain;
  2. public class Department {
  3. private Integer id;
  4. private String name;
  5. public Integer getId() {
  6. return id;
  7. }
  8. public void setId(Integer id) {
  9. this.id = id;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. @Override
  18. public String toString() {
  19. return "Department{" +
  20. "id=" + id +
  21. ", name='" + name + '\'' +
  22. '}';
  23. }
  24. }
  • 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. private Department department;
  10. public Integer getId() {
  11. return id;
  12. }
  13. public void setId(Integer id) {
  14. this.id = id;
  15. }
  16. public String getLastName() {
  17. return lastName;
  18. }
  19. public void setLastName(String lastName) {
  20. this.lastName = lastName;
  21. }
  22. public String getEmail() {
  23. return email;
  24. }
  25. public void setEmail(String email) {
  26. this.email = email;
  27. }
  28. public String getGender() {
  29. return gender;
  30. }
  31. public void setGender(String gender) {
  32. this.gender = gender;
  33. }
  34. @Override
  35. public String toString() {
  36. return "Employee{" +
  37. "id=" + id +
  38. ", lastName='" + lastName + '\'' +
  39. ", email='" + email + '\'' +
  40. ", gender='" + gender + '\'' +
  41. ", department=" + department +
  42. '}';
  43. }
  44. }
  • DepartmentMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Department;
  3. public interface DepartmentMapper {
  4. Department findById(Integer id);
  5. }
  • DepartmentMapper.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.DepartmentMapper">
  6. <select id="findById" resultType="com.sunxiaping.domain.Department">
  7. SELECT *
  8. FROM department
  9. WHERE id = #{id,jdbcType=INTEGER}
  10. </select>
  11. </mapper>
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. Employee findEmpAndDeptById(Integer id);
  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. <resultMap id="emp" type="com.sunxiaping.domain.Employee">
  7. <!--
  8. 分步查询:
  9. ①按照员工id查询员工信息
  10. ②根据查询员工信息中的department_id去部门表中查询部门信息
  11. ③部门设置到员工中
  12. -->
  13. <id property="id" column="id"/>
  14. <result property="lastName" column="last_name"/>
  15. <result property="email" column="email"/>
  16. <result property="gender" column="gender"/>
  17. <!--
  18. association 定义关联对象的封装规则
  19. property:关联对象的属性
  20. select:表明当前属性是调用select查询的结果
  21. column:指定将那一列的值传给这个方法
  22. 流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的关联对象的属性
  23. -->
  24. <association property="department" select="com.sunxiaping.mapper.DepartmentMapper.findById" column="did" />
  25. </resultMap>
  26. <select id="findEmpAndDeptById" resultMap="emp">
  27. SELECT e.id as id,e.last_name as last_name,e.gender as gender,e.email as email,e.department_id as did
  28. FROM employee e
  29. WHERE e.id = #{id,jdbcType=INTEGER}
  30. </select>
  31. </mapper>

分步查询中使用延迟加载:需要在 mybatis-config.xml 中配置如下的全局设置

  1. <settings>
  2. <!-- 开启自动驼峰命名规则映射 -->
  3. <setting name="mapUnderscoreToCamelCase" value="true"/>
  4. <!-- 开启对jdbcType的NULL的支持 -->
  5. <setting name="jdbcTypeForNull" value="NULL"/>
  6. <!-- 开启延迟加载 -->
  7. <setting name="lazyLoadingEnabled" value="true"/>
  8. <!-- 开启按需加载 -->
  9. <setting name="aggressiveLazyLoading" value="false"/>
  10. </settings>

5.3.2.5 collection 定义关联集合封装规则

  • 示例:查询一个部门信息的同时并查询下面的所有员工信息
  • 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. }
  • Department.java
  1. package com.sunxiaping.domain;
  2. import java.util.List;
  3. public class Department {
  4. private Integer id;
  5. private String name;
  6. private List<Employee> employees;
  7. public Integer getId() {
  8. return id;
  9. }
  10. public void setId(Integer id) {
  11. this.id = id;
  12. }
  13. public String getName() {
  14. return name;
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. public List<Employee> getEmployees() {
  20. return employees;
  21. }
  22. public void setEmployees(List<Employee> employees) {
  23. this.employees = employees;
  24. }
  25. @Override
  26. public String toString() {
  27. return "Department{" +
  28. "id=" + id +
  29. ", name='" + name + '\'' +
  30. ", employees=" + employees +
  31. '}';
  32. }
  33. }
  • DepartmentMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Department;
  3. public interface DepartmentMapper {
  4. Department findById(Integer id);
  5. }
  • DepartmentMapper.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.DepartmentMapper">
  6. <resultMap id="dept" type="com.sunxiaping.domain.Department">
  7. <id property="id" column="id"/>
  8. <result property="name" column="name"/>
  9. <!--
  10. collection 定义关联集合类型的属性的封装规则
  11. ofType 定义集合中元素的类型
  12. -->
  13. <collection property="employees" ofType="com.sunxiaping.domain.Employee">
  14. <!-- 定义这个集合中元素的封装规则 -->
  15. <id property="id" column="eid"/>
  16. <result property="lastName" column="lastName"/>
  17. <result property="gender" column="gender"/>
  18. <result property="email" column="email"/>
  19. </collection>
  20. </resultMap>
  21. <select id="findById" resultMap="dept">
  22. SELECT d.id as id,d.name as name,e.id as eid,e.last_name as lastName,e.email as email,e.gender as gender
  23. FROM department d
  24. INNER JOIN employee e
  25. ON d.id = e.department_id
  26. WHERE d.id = #{id,jdbcType=INTEGER}
  27. </select>
  28. </mapper>

5.3.2.6 collection 定义分步查询

  • 示例:查询一个部门信息的同时并查询下面的所有员工信息
  • 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. }
  • Department.java
  1. package com.sunxiaping.domain;
  2. import java.util.List;
  3. public class Department {
  4. private Integer id;
  5. private String name;
  6. private List<Employee> employees;
  7. public Integer getId() {
  8. return id;
  9. }
  10. public void setId(Integer id) {
  11. this.id = id;
  12. }
  13. public String getName() {
  14. return name;
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. public List<Employee> getEmployees() {
  20. return employees;
  21. }
  22. public void setEmployees(List<Employee> employees) {
  23. this.employees = employees;
  24. }
  25. @Override
  26. public String toString() {
  27. return "Department{" +
  28. "id=" + id +
  29. ", name='" + name + '\'' +
  30. ", employees=" + employees +
  31. '}';
  32. }
  33. }
  • EmployeeMapper.java
package com.sunxiaping.mapper;

import com.sunxiaping.domain.Employee;

import java.util.List;

public interface EmployeeMapper {

    List<Employee> findByDepatmentId(Integer departmentId);

}
  • EmployeeMapper.xml
<?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="com.sunxiaping.mapper.EmployeeMapper">

    <resultMap id="emp" type="com.sunxiaping.domain.Employee">

        <id property="id" column="id"/>
        <result property="lastName" column="last_name"/>
        <result property="email" column="email"/>
        <result property="gender" column="gender"/>
    </resultMap>

    <select id="findByDepatmentId" resultMap="emp">
        SELECT e.id as id,e.last_name as last_name,e.gender as gender,e.email as email,e.department_id as did
        FROM employee e
        WHERE e.department_id = #{departmentId,jdbcType=INTEGER}
    </select>
</mapper>
  • DepartmentMapper.java
package com.sunxiaping.mapper;

import com.sunxiaping.domain.Department;

public interface DepartmentMapper {

    Department findById(Integer id);

}
  • DepartmentMapper.xml
<?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="com.sunxiaping.mapper.DepartmentMapper">

    <resultMap id="dept" type="com.sunxiaping.domain.Department">
        <id property="id" column="id"/>
        <result property="name" column="name"/>

        <collection property="employees" select="com.sunxiaping.mapper.EmployeeMapper.findByDepatmentId" column="{id}">
        </collection>
    </resultMap>

    <select id="findById" resultMap="dept">
        SELECT d.id as id,d.name as name
        FROM department d
        WHERE d.id = #{id,jdbcType=INTEGER}
    </select>
</mapper>

5.2.3.7 分步查询传递多列值

  • 有的时候,分步查询不是传递一个值,而是传递多列值,这个时候我们需要使用 {key1=column1,key2=clomn2…} 的形式来多列值封装 map 传递。

  • 示例:

  • DepartmentMapper.xml
<?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="com.sunxiaping.mapper.DepartmentMapper">

    <resultMap id="dept" type="com.sunxiaping.domain.Department">
        <id property="id" column="id"/>
        <result property="name" column="name"/>

        <collection property="employees" select="com.sunxiaping.mapper.EmployeeMapper.findByDepatmentId" column="{departmentId=id}">
        </collection>
    </resultMap>

    <select id="findById" resultMap="dept">
        SELECT d.id as id,d.name as name
        FROM department d
        WHERE d.id = #{id,jdbcType=INTEGER}
    </select>
</mapper>

5.2.3.8 fetchType

  • 在 collection 和 association 标签的 fetchType 属性有 eager 和 lazy 属性,其中 eager 属性表示立即加载,而 lazy 属性表示延迟加载。一旦指定了 fetchType 可以覆盖全局的延迟加载策略。

5.2.3.9 discriminator 鉴别器

  • Mybatis 可以使用 discriminator 判断某列的值,然后根据某列的值改变封装行为。

  • 示例:判断 Employee,如果查出的是女生,就把部门信息查询出来,否则不查询;如果查询出来的是男生,就把 last_name 这一列的值赋值给 email

  • Department.java
package com.sunxiaping.domain;

public class Department {

    private Integer id;

    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Department{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
  • Employee.java
package com.sunxiaping.domain;

import org.apache.ibatis.type.Alias;

@Alias("emp")
public class Employee {

    private Integer id;

    private String lastName;

    private String email;

    private String gender;

    private Department department;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", gender='" + gender + '\'' +
                ", department=" + department +
                '}';
    }
}
  • DepartmentMapper.java
package com.sunxiaping.mapper;

import com.sunxiaping.domain.Department;

public interface DepartmentMapper {

    Department findById(Integer id);

}
  • DepartmentMapper.xml
<?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="com.sunxiaping.mapper.DepartmentMapper">

    <resultMap id="dept" type="com.sunxiaping.domain.Department">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
    </resultMap>

    <select id="findById" resultMap="dept">
        SELECT d.id as id,d.name as name
        FROM department d
        WHERE d.id = #{id,jdbcType=INTEGER}
    </select>
</mapper>
  • EmployeeMapper.java
package com.sunxiaping.mapper;

import com.sunxiaping.domain.Employee;

public interface EmployeeMapper {

    Employee findById(Integer id);

}
  • EmployeeMapper.xml
<?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="com.sunxiaping.mapper.EmployeeMapper">

    <resultMap id="emp" type="com.sunxiaping.domain.Employee">

        <id property="id" column="id"/>
        <result property="lastName" column="last_name"/>
        <result property="email" column="email"/>
        <result property="gender" column="gender"/>
        <!--
            discriminator 鉴别器
             column:指定要判断的列名
             javaType:指定要判断的列对应的java类型
        -->
        <discriminator javaType="string" column="gender">
            <case value="女" resultType="com.sunxiaping.domain.Employee">
                <association property="department" javaType="java.lang.Integer" select="com.sunxiaping.mapper.DepartmentMapper.findById" column="did"/>
            </case>
            <case value="男" resultType="com.sunxiaping.domain.Employee">
                <id property="id" column="id"/>
                <result property="lastName" column="last_name"/>
                <result property="email" column="last_name"/>
                <result property="gender" column="gender"/>
            </case>
        </discriminator>

    </resultMap>


    <select id="findById" resultMap="emp">
        SELECT e.id as id,e.last_name as last_name,e.gender as gender,e.email as email,e.department_id as did
        FROM employee e
        WHERE e.department_id = #{departmentId,jdbcType=INTEGER}
    </select>
</mapper>