文章目录
- 第一章:概述
- 第二章:properties (了解)
- 第三章:settings
- 第四章:typeAliases (别名处理器)
- 第五章:typeHandlers (类型处理器)
- 第六章:plugins(插件)
- 第七章:environments (环境)
- 第八章:databaseIdProvider
- 第九章:mapper(映射)
- Mybatis 的映射文件
- 第一章:增删改查
- 第二章:INSERT 获取自增主键的值
- 第三章:INSERT 获取非自增主键的值
- 第四章:参数处理
- 4.1 单个参数
- 4.2 多个参数
- 4.3 命名参数
- 4.4 POJO
- 4.5 Map
- 4.6 TO
- 4.7 Collection 类型(List类型、Set类型)数组类型
- 4.9 #取值时指定参数的相关规则
- 第五章:select 元素
- 5.1 概述
- 5.2 resultType
- 5.2.1 返回 List
- 5.2.2 返回 Map
- 5.3 resultMap
- 5.3.1 自定义结果映射规则
- 5.3.2 关联查询
- 5.3.2.1 环境搭建
- 5.3.2.2 级联属性封装查询结果
- 5.3.2.3 association 定义关联对象
- 5.3.2.4 association 分步查询
- 分步查询中使用延迟加载:需要在 mybatis-config.xml 中配置如下的全局设置
- 5.3.2.5 collection 定义关联集合封装规则
- 5.3.2.6 collection 定义分步查询
- 5.2.3.7 分步查询传递多列值
- 5.2.3.8 fetchType
- 5.2.3.9 discriminator 鉴别器
- 小结
第一章:概述
- Mybatis 的全局配置文件包含了影响 Mybatis 行为甚深的设置( settings )和属性( properties )信息。
- 文档的顶层结构如下:
- Configuration 配置:
- properties 属性
- settings 设置
- typeAliases 类型命名
- typeHandlers 类型处理器
- objectFactory 对象工厂
- plugins 插件
- environments 环境
- environment 环境变量
- transactionManager 事务管理器
- dataSource 数据源
- databaseIdProvider 数据库厂商标识
- mappers 映射器
- Configuration 配置:
第二章:properties (了解)
●Mybatis 可以使用 properties 标签来引入外部的 properties 属性配置文件中的内容。
●属性:
○resource:引入类路径下的配置文件。
○url:引入网络或磁盘上的配置文件。
●示例:
- db.properties
jdbc.url=jdbc:mysql://192.168.134.100:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.username=root
jdbc.password=123456
- mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--Mybatis可以使用properties标签来引入外部properties配置文件的内容resource属性:引入类路径下的配置文件url属性:引入网络或磁盘上的配置文件--><properties resource="db.properties" ></properties><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><mapper resource="com/xuguoguo/mapper/EmployeeMapper.xml"/></mappers>
</configuration>
第三章:settings
-
这是 Mybatis 中极为重要的调整设置,它们会改变 Mybatis 的运行时行为。
-
示例:
-
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--Mybatis可以使用properties标签来引入外部properties配置文件的内容resource属性:引入类路径下的配置文件url属性:引入网络或磁盘上的配置文件--><properties resource="db.properties" ></properties><settings><!-- 开启自动驼峰命名规则映射,可以将诸如last_name封装为lastName。--><setting name="mapUnderscoreToCamelCase" value="true"/></settings><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><mapper resource="com/xuguoguo/mapper/EmployeeMapper.xml"/></mappers>
</configuration>
第四章:typeAliases (别名处理器)
- 类型别名是为 Java 类型设置一个短的名字,可以方便我们引用某个类。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--Mybatis可以使用properties标签来引入外部properties配置文件的内容resource属性:引入类路径下的配置文件url属性:引入网络或磁盘上的配置文件--><properties resource="db.properties" ></properties><settings><!-- 开启自动驼峰命名规则映射 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><!--类型别名是为Java类型设置一个短的名字,可以方便我们引用某个类--><typeAlias type="com.xuguoguo.domain.Employee" alias="emp"/></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><mapper resource="com/xuguoguo/mapper/EmployeeMapper.xml"/></mappers>
</configuration>
- 在类很多的情况下,可以批量设置别名。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--Mybatis可以使用properties标签来引入外部properties配置文件的内容resource属性:引入类路径下的配置文件url属性:引入网络或磁盘上的配置文件--><properties resource="db.properties" ></properties><settings><!-- 开启自动驼峰命名规则映射 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><!-- 通过package标签的name属性指定需要生成别名的包,默认会创建一个别名,就是类名的小写--><package name="com.xuguoguo"/></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><mapper resource="com/xuguoguo/mapper/EmployeeMapper.xml"/></mappers>
</configuration>
- 可以在类上使用 @Alias 注解设置别名:
package com.xuguoguo.domain;import org.apache.ibatis.type.Alias;@Alias("emp")
public class Employee {private Integer id;private String lastName;private String email;private String gender;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;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", lastName='" + lastName + '\'' +", email='" + email + '\'' +", gender='" + gender + '\'' +'}';}
}
- 需要注意的是,Mybatis 已经为许多常见的 Java 类型内建了相应的类型别名。它们都是大小写不敏感的,我们在起别名的时候千万不要占用已有的别名。
- 别名映射的类型
- 别名映射的类型
第五章:typeHandlers (类型处理器)
-
无论是 Mybatis 在预处理语句( PreparedStatement )中设置一个参数时,还是从结果集中取出一个值的时候,都会用类型处理器将获取的值以合适的方式转换为 Java 类型。
-
日期类型的处理:JDK 1.8 以前一直是个头疼的问题。我们通常使用 JSR 310 规范领导者 Stephen Colebourne 创建的 Joda-Time 来操作。JDK 1.8 已经实现全部的 JSR 310 规范了。日期时间处理上,我们可以使用 Mybatis 基于 JSR 310 编写的各种日期时间类型处理器。Mybatis 3.4 以前的版本需要我们手动注册这些处理器,以后的版本都是自动注册的。
-
自定义类型处理器:我们可以重写类型处理器或者创建自己的类型处理器来处理器不支持的或非标准的类型。
-
步骤:
-
① 实现 org.apche.ibatis.type.TypeHandler 接口或者继承 org.apche.ibatis.type.BaseTypeHandler 。
-
② 指定其映射某个 JDBC 类型。
-
③ 在 Mybatis 的全局配置文件中注册。
第六章:plugins(插件)
- 插件是 Mybatis 提供的一个非常强大的机制,我们可以通过插件来修改 Mybatis 的一些核心行为。插件通过动态代理机制,可以介入四大对象的任何一个方法的执行。
Executor(update, query, flushStatements, commit, rollback,getTransaction, close, isClosed)
ParameterHandler(getParameterObject, setParameters)
ResultSetHandler(handleResultSets, handleOutputParameters)
StatementHandler(prepare, parameterize, batch, update, query)
第七章:environments (环境)
-
Mybatis 可以配置多种环境,比如开发、测试和生产环境需要有不同的配置。
-
每种环境使用一个 environment 标签进行配置并指定唯一标识符。
-
可以通过 environments 标签中的 default 属性指定一个环境的标识符来快速的切换环境。
-
environment:指定具体环境
- id:指定当前环境的唯一标识。
- transactionManager:事务管理器。
- type:事务管理器的类型。有 JDBC 、MANAGED 和自定义类型。
- JDBC:使用了 JDBC 的提交和回滚设置,依赖于从数据源得到的连接来管理事务范围。
- MANAGED:不提交或回滚一个连接、让容器来管理事务的整个生命周期。
- 自定义:实现 TransactionFactory 接口,type = 全类名/别名。
- type:事务管理器的类型。有 JDBC 、MANAGED 和自定义类型。
- dataSource:数据源。
- type:数据源类型。有 UNPOOLED、POOLED、JNDI 和自定义类型。
- UNPOOLED:不使用连接池。
- POOLED:使用连接池。
- JNDI:在EJB或应用服务器这类容器中查找指定的数据源。
- 自定义:实现 DataSourceFactory 接口,定义数据源的获取方式。
- type:数据源类型。有 UNPOOLED、POOLED、JNDI 和自定义类型。
-
示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--Mybatis可以使用properties标签来引入外部properties配置文件的内容resource属性:引入类路径下的配置文件url属性:引入网络或磁盘上的配置文件--><properties resource="db.properties" ></properties><settings><!-- 开启自动驼峰命名规则映射 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><!--通过package标签的name指定需要生成别名的包,默认会创建一个别名,就是类名的小写--><package name="com.xuguoguo"/></typeAliases><!--environments,Mybatis可以配置多种环境environment:配置一个具体的环境信息;必须有transactionManager和dataSource标签。属性id代表当前环境的标识,可以达到快速切换环境transactionManager:事务管理器type:事务管理器的类型,有JDBC和MANAGED两种类型,还可以自定义事务管理器dataSource:数据源type:数据源的类型,有UNPOOLED、POOLED、JNDI和自定义类型。--><environments default="development"><environment id="test"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><mapper resource="com/xuguoguo/mapper/EmployeeMapper.xml"/></mappers>
</configuration>
第八章:databaseIdProvider
- Mybatis 可以根据不同的数据库厂商执行不同的语句。
<databaseIdProvider type="DB_VENDOR"><!--为不同的数据库厂商起别名--><property name="MySQL" value="mysql"/><property name="Oracle" value="oracle"/><property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>
-
databaseIdProvider 标签的属性 type 的值是 DB_VENDOR ,会通过 DatabaseMetaData 中的 getDatabaseProductName() 方法返回的字符串进行设置。由于通常情况下这个字符串非常长而且相同产品的不同版本会返回不同的值,所以最好通过设置属性别名来使其变短。
-
Mybatis 的匹配规则如下:
- ① 如果没有配置 databaseIdProvider 标签,那么 databaseId 的值就为 null 。
- ② 如果配置了 databaseIdProvider 标签,使用标签配置的name去匹配数据库的信息,匹配上设置 databaseId = 配置指定的值,否则依旧为 null 。
- ③ 如果 databaseId 不为 null ,Mybatis 只会找到配置 databaseId 的 SQL 语句。
- ④ Mybatis 会同时加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。如果同时找到带有 databaseId 和不带databaseId 的相同语句,则后者会被舍弃。
-
示例:
-
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--Mybatis可以使用properties标签来引入外部properties配置文件的内容resource属性:引入类路径下的配置文件url属性:引入网络或磁盘上的配置文件--><properties resource="db.properties"></properties><settings><!-- 开启自动驼峰命名规则映射 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><!--通过package标签的name指定需要生成别名的包,默认会创建一个别名,就是类名的小写--><package name="com.xuguoguo"/></typeAliases><!--environments,Mybatis可以配置多种环境environment:配置一个具体的环境信息;必须有transactionManager和dataSource标签。属性id代表当前环境的标识,可以达到快速切换环境transactionManager:事务管理器type:事务管理器的类型,有JDBC和MANAGED两种类型,还可以自定义事务管理器dataSource:数据源type:数据源的类型,有UNPOOLED、POOLED、JNDI和自定义类型。--><environments default="development"><environment id="test"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><!--databaseIdProvider:支持多数据库厂商type="DB_VENDOR":VendorDatabaseIdProvider- 作用: 得到数据库厂商的标识(驱动,Connection接口中的getMetaData()返回了DatabaseMetaData,DatabaseMetaData中有getDatabaseProductName()方法),Mybatis就能数据数据库厂商标识来指定不同的SQL--><databaseIdProvider type="DB_VENDOR"><!--为不同的数据库厂商起别名--><property name="MySQL" value="mysql"/><property name="Oracle" value="oracle"/><property name="SQL Server" value="sqlserver"/></databaseIdProvider><mappers><mapper resource="com/xuguoguo/mapper/EmployeeMapper.xml"/></mappers>
</configuration>
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findById" resultType="com.xuguoguo.domain.Employee">SELECT id,last_name as lastName,email,genderFROM employeeWHERE id = #{id,jdbcType=INTEGER}</select><!--select标签中databaseId用来指定在那种数据库环境下执行--><select id="findById" resultType="com.xuguoguo.domain.Employee" databaseId="mysql">SELECT id,last_name as lastName,email,genderFROM employeeWHERE id = #{id,jdbcType=INTEGER}</select><!--select标签中databaseId用来指定在那种数据库环境下执行--><select id="findById" resultType="com.xuguoguo.domain.Employee" databaseId="oracle">SELECT id,last_name as lastName,email,genderFROM employeesWHERE id = #{id,jdbcType=INTEGER}</select>
</mapper>
第九章:mapper(映射)
- mapper 逐个注册 SQL 映射文件
<mappers>
<mapper resource="com/xuguoguo/mapper/EmployeeMapper.xml"/>
</mappers>
- 使用批量注册:如果有 SQL 映射文件存在,文件名必须和 Mapper 接口名相同且必须在同一个目录下
<mappers><package name="com.xuguoguo.mapper"/>
</mappers>
- 示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--Mybatis可以使用properties标签来引入外部properties配置文件的内容resource属性:引入类路径下的配置文件url属性:引入网络或磁盘上的配置文件--><properties resource="db.properties"></properties><settings><!-- 开启自动驼峰命名规则映射 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><!--通过package标签的name指定需要生成别名的包,默认会创建一个别名,就是类名的小写--><package name="com.xuguoguo"/></typeAliases><!--environments,Mybatis可以配置多种环境environment:配置一个具体的环境信息;必须有transactionManager和dataSource标签。属性id代表当前环境的标识,可以达到快速切换环境transactionManager:事务管理器type:事务管理器的类型,有JDBC和MANAGED两种类型,还可以自定义事务管理器dataSource:数据源type:数据源的类型,有UNPOOLED、POOLED、JNDI和自定义类型。--><environments default="development"><environment id="test"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><!--databaseIdProvider:支持多数据库厂商type="DB_VENDOR":VendorDatabaseIdProvider- 作用: 得到数据库厂商的标识(驱动,Connection接口中的getMetaData()返回了DatabaseMetaData,DatabaseMetaData中有getDatabaseProductName()方法),Mybatis就能数据数据库厂商标识来指定不同的SQL--><databaseIdProvider type="DB_VENDOR"><!--为不同的数据库厂商起别名--><property name="MySQL" value="mysql"/><property name="Oracle" value="oracle"/><property name="SQL Server" value="sqlserver"/></databaseIdProvider><!--mappers将SQL映射注册到全局配置中--><mappers><!--mapper:注册一个SQL映射- resource:引用类路径下的SQL映射文件- url:引用网络路径下的SQL映射文件- class:引用接口,- 有SQL配置文件,接口和配置文件必须放在同一目录下,且接口名和配置文件的名称必须相同- 没有SQL配置文件,所有的SQL都是利用注解写在接口上--><!-- mapper resource="com/xuguoguo/mapper/EmployeeMapper.xml"/>--><!--package:批量注册,如果有SQL配置文件,接口和配置文件必须放在同一目录下,且接口名和配置文件的名称必须相同--><package name="com.xuguoguo.mapper"/></mappers></configuration>
Mybatis 的映射文件
第一章:增删改查
●示例:
●导入相关 jar 包的 Maven 坐标:
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version>
</dependency>
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version>
</dependency>
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope>
</dependency>
- db.properties
jdbc.url=jdbc:mysql://192.168.134.100:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.username=root
jdbc.password=123456
- log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"><log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"><appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"><param name="Encoding" value="UTF-8" /><layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /></layout></appender><logger name="java.sql"><level value="debug" /></logger><logger name="org.apache.ibatis"><level value="info" /></logger><root><level value="debug" /><appender-ref ref="STDOUT" /></root>
</log4j:configuration>
- Employee.java
package com.xuguoguo.domain;import org.apache.ibatis.type.Alias;@Alias("emp")
public class Employee {private Integer id;private String lastName;private String email;private String gender;public Employee() {}public Employee(Integer id, String lastName, String email, String gender) {this.id = id;this.lastName = lastName;this.email = email;this.gender = gender;}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;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", lastName='" + lastName + '\'' +", email='" + email + '\'' +", gender='" + gender + '\'' +'}';}
}
- EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;public interface EmployeeMapper {/*** 根据id查询员工的信息** @param id* @return*/Employee findById(Integer id);/*** 增加员工信息** @param employee*/void addEmp(Employee employee);/*** 修改员工信息** @param employee*/void updateEmp(Employee employee);/*** 根据id删除员工信息** @param id*/void deleteEmpById(Integer id);}
- EmployeeMapper.xml
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findById" resultType="com.xuguoguo.domain.Employee">SELECT id,last_name as lastName,email,genderFROM employeeWHERE id = #{id,jdbcType=INTEGER}</select><insert id="addEmp">INSERT INTO employee (last_name,email,gender)VALUES (#{lastName,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{gender,jdbcType=VARCHAR})</insert><update id="updateEmp">UPDATE employeeSET last_name = #{lastName,jdbcType=VARCHAR},email = #{email,jdbcType=VARCHAR},gender=#{gender,jdbcType=VARCHAR}WHERE id = #{id,jdbcType=INTEGER}</update><delete id="deleteEmpById">DELETE FROM employeeWHERE id = #{id,jdbcType=INTEGER}</delete>
</mapper>
- mybatis-copnfig.xml```xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="db.properties"></properties><settings><!-- 开启自动驼峰命名规则映射 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 使用${}引入db.properties属性文件中的内容 --><property name="driver" value="${jdbc.driverClass}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><package name="com.xuguoguo.mapper"/></mappers></configuration>
- 测试:
package com.xuguoguo;import com.xuguoguo.domain.Employee;
import com.xuguoguo.mapper.EmployeeMapper;
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 java.io.IOException;
import java.io.InputStream;public class EmployeeTest {SqlSessionFactory sqlSessionFactory = null;SqlSession sqlSession = null;EmployeeMapper employeeMapper = null;@Beforepublic void before() throws IOException {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);sqlSession = sqlSessionFactory.openSession(true);employeeMapper = sqlSession.getMapper(EmployeeMapper.class);}@Afterpublic void after() {if (null != sqlSession) {sqlSession.close();}}@Testpublic void testFindById() {Employee employee = employeeMapper.findById(1);System.out.println("employee = " + employee);}@Testpublic void testAddEmp() {Employee employee = new Employee();employee.setEmail("jerry@qq.com");employee.setGender("男");employee.setLastName("jerry");employeeMapper.addEmp(employee);}@Testpublic void testUpdateEmp(){Employee employee = employeeMapper.findById(2);employee.setGender("女");employeeMapper.updateEmp(employee);}@Testpublic void testDeleteEmpById(){employeeMapper.deleteEmpById(2);}}
第二章:INSERT 获取自增主键的值
-
MySQL 等数据库支持自增主键,自增主键的值是通过 statement.getGenerateKeys() 方法获取的。
-
通过使用
useGeneratedKeys=“true” 开启自增主键获取主键值的策略。 -
通过使用
keyProperty=“id” 指定对应的主键属性,Mybatis 获取主键值以后,将这个值封装给 JavaBean 的哪个属性。 -
示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><!--MySQL支持自增主键,自增主键值的获取,Mybatis是利用statement.getGeneratedKeys()useGeneratedKeys="true":使用自增主键获取主键值策略keyProperty="id":指定对应的主键属性,Mybatis获取主键值以后,将这个值封装给JavaBean的哪个属性--><insert id="addEmp" useGeneratedKeys="true" keyProperty="id" parameterType="com.xuguoguo.domain.Employee">INSERT INTO employee (last_name,email,gender)VALUES (#{lastName,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{gender,jdbcType=VARCHAR})</insert>
</mapper>
第三章:INSERT 获取非自增主键的值
-
Oracle 不支持自增主键,Oracle 是使用序列来模拟自增的。
-
每次插入的数据的主键都是从序列中拿到的值。
-
示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><!--Oracle不支持自增主键,Oracle是使用序列来模拟自增的。每次插入的数据的主键都是从序列中拿到的值。--><insert id="addEmp" useGeneratedKeys="true" keyProperty="id" parameterType="com.xuguoguo.domain.Employee"><!--插入时的主键是从序列中拿到的keyProperty:查询的主键封装给JavaBean的哪个属性order:- BEFORE:当前的SQL在插入SQL之前运行- 运行顺序:先运行selectKey中的SQL语句,查询出id,然后将id封装给JavaBean中的id属性,在运行插入SQL的时候,就可以取出id属性对应的值- AFTER: 先运行插入SQL,再运行当前的SQL - 运行顺序:先运行插入的SQL(会从序列中取出新值作为id),再运行selectKey查询id,然后将id封装给JavaBean的id属性,并发情况下可能有问题。resultType:查出的数据的返回值类型--><selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Integer"><!--编写查询主键的SQL语句-->SELECT employee_seq.nextval FROM dual</selectKey>INSERT INTO employee (id,last_name,email,gender)VALUES (#{id,jdbcType=INTEGER},#{lastName,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{gender,jdbcType=VARCHAR})</insert>
</mapper>
- 示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><!--Oracle不支持自增主键,Oracle是使用序列来模拟自增的。每次插入的数据的主键都是从序列中拿到的值。--><insert id="addEmp" useGeneratedKeys="true" keyProperty="id" parameterType="com.xuguoguo.domain.Employee"><!--插入时的主键是从序列中拿到的keyProperty:查询的主键封装给JavaBean的哪个属性order:- BEFORE:当前的SQL在插入SQL之前运行- 运行顺序:先运行selectKey中的SQL语句,查询出id,然后将id封装给JavaBean中的id属性,在运行插入SQL的时候,就可以取出id属性对应的值- AFTER: 先运行插入SQL,再运行当前的SQL- 运行顺序:先运行插入的SQL(会从序列中取出新值作为id),再运行selectKey查询id,然后将id封装给JavaBean的id属性,并发情况下可能有问题。resultType:查出的数据的返回值类型--><selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"><!--编写查询主键的SQL语句-->SELECT employee_seq.currval FROM dual</selectKey>INSERT INTO employee (id,last_name,email,gender)VALUES (employee_seq.nextval},#{lastName,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{gender,jdbcType=VARCHAR})</insert>
</mapper>
第四章:参数处理
4.1 单个参数
-
Mybatis 不需要经过任何处理,Mybatis 可以直接使用
#{参数名} 取出参数值。 -
示例:
-
EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;public interface EmployeeMapper {/*** 根据id查询员工的信息** @param id* @return*/Employee findById(Integer id);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findById" resultType="com.xuguoguo.domain.Employee">SELECT id,last_name as lastName,email,genderFROM employeeWHERE id = #{abc,jdbcType=INTEGER}</select>
</mapper>
4.2 多个参数
-
任意多个参数,都会被 Mybatis 重新包装成一个 Map 传入。Map 中的 key 就是 param1, param2 ,…,value 是传入的参数值。
-
#{}
就是从 map 中获取指定的 key 的值。 -
示例:
-
EmployeeMapper.java
package com.xuguoguo.mapper;
import com.xuguoguo.domain.Employee;
public interface EmployeeMapper {
/**
* 根据id和lastName查询员工信息
*
* @param id
* @param lastName
* @return
*/
Employee findByIdAndLastName(Integer id, String lastName);
}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findByIdAndLastName" resultType="com.xuguoguo.domain.Employee">SELECT id,last_name as lastName,email,genderFROM employeeWHERE id = #{param1,jdbcType=INTEGER} AND last_name = #{param2,jdbcType=VARCHAR}</select></mapper>
4.3 命名参数
-
当多个参数的时候,可以使用
- @Param 注解明确指定 Mybatis 中传入参数 Map 中的 key ,Map 中的 key 就是使用
- @Param 注解指定的值,value 就是传入的参数值。
-
#{指定的key}
就可以取出对应的参数值。 -
示例:
-
Employee.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;
import org.apache.ibatis.annotations.Param;public interface EmployeeMapper {/*** 根据id和lastName查询员工信息** @param id* @param lastName* @return*/Employee findByIdAndLastName(@Param("id") Integer id,@Param("lastName") String lastName);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findByIdAndLastName" resultType="com.xuguoguo.domain.Employee">SELECT id,last_name as lastName,email,genderFROM employeeWHERE id = #{id,jdbcType=INTEGER} AND last_name = #{lastName,jdbcType=VARCHAR}</select></mapper>
4.4 POJO
-
如果多个参数正好是业务逻辑的数据模型,我们就可以直接传入 POJO 。
#{属性名} 取出传入 POJO 的属性值。 -
示例:
-
EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;public interface EmployeeMapper {Employee findByPOJO(Employee employee);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findByPOJO" resultType="com.xuguoguo.domain.Employee">SELECT id,last_name as lastName,email,genderFROM employeeWHERE id = #{id,jdbcType=INTEGER} AND last_name = #{lastName,jdbcType=VARCHAR}</select></mapper>
4.5 Map
-
如果多个参数不是业务模型的数据,没有对应的 POJO ,不经常使用,为了方便,我们可以传入 Map 。
-
#{key}
取出传入 map 中对应的值。 -
示例:
-
EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;import java.util.Map;public interface EmployeeMapper {Employee findByMap(Map<String, Object> map);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findByMap" resultType="com.xuguoguo.domain.Employee">SELECT id,last_name as lastName,email,genderFROM employeeWHERE id = #{id,jdbcType=INTEGER} AND last_name = #{lastName,jdbcType=VARCHAR}</select></mapper>
4.6 TO
-
如果多个参数不是业务模型中的数据,但是经常使用,推荐编写一个 TO(Transfer Object)数据传输对象。
-
示例:
-
Page.java
package com.xuguoguo.to;/*** 分页的参数*/
public class Page {/*** 每页显示条数*/private Integer pageSize;/*** 起始页码*/private Integer pageNum;public Integer getPageSize() {return pageSize;}public void setPageSize(Integer pageSize) {this.pageSize = pageSize;}public Integer getPageNum() {return pageNum;}public void setPageNum(Integer pageNum) {this.pageNum = pageNum;}@Overridepublic String toString() {return "Page{" +"pageSize=" + pageSize +", pageNum=" + pageNum +'}';}
}
- EmployeeMapper.java
package com.xuguoguo.mapper;
import com.xuguoguo.domain.Employee;
import com.xuguoguo.to.Page;
import java.util.List;
public interface EmployeeMapper {List<Employee> findByPage(Page page);
}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findByPage" resultType="com.xuguoguo.domain.Employee">SELECT id,last_name as lastName,email,genderFROM employeeLIMIT #{pageNum},#{pageSize}</select>
</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
package com.xuguoguo.mapper;
import com.xuguoguo.domain.Employee;
import java.util.List;
import java.util.Set;
public interface EmployeeMapper {List<Employee> findBySet(Set<Integer> id);
}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findBySet" resultType="com.xuguoguo.domain.Employee">SELECT id,last_name as lastName,email,genderFROM employeeWHERE id = #{collection}</select>
</mapper>
4.8 # 和 $ 取值区别
-
#{}
获取参数的值,预编译到 SQL 中,安全。 -
${}
获取参数的值,拼接到 SQL 中,有 SQL 注入问题。 -
注意:
-
大多数情况下,我们取参数的值的时候使用
#{} 。 -
原生 JDBC 不支持占位符的地方,我们就可以使用
${} 。 -
比如:排序
-
比如:财务系统在设计之初按照年份分表,查询的时候应该这样写:
Order BY ${name}
SELECT * FROM ${year}_salary WHERE xxx;
- 示例:
- EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;import java.util.Map;public interface EmployeeMapper {Employee findByMap(Map<String,Object> map);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findByMap" resultType="com.xuguoguo.domain.Employee" parameterType="java.util.Map">SELECT id,last_name as lastName,email,genderFROM ${tableName}WHERE id = #{id}</select></mapper>
- 测试:
package com.xuguoguo;import com.xuguoguo.domain.Employee;
import com.xuguoguo.mapper.EmployeeMapper;
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 java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;public class EmployeeTest {SqlSessionFactory sqlSessionFactory = null;SqlSession sqlSession = null;EmployeeMapper employeeMapper = null;@Beforepublic void before() throws IOException {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);sqlSession = sqlSessionFactory.openSession(true);employeeMapper = sqlSession.getMapper(EmployeeMapper.class);}@Afterpublic void after() {if (null != sqlSession) {sqlSession.close();}}@Testpublic void testFindById() {Map<String, Object> map = new HashMap<>();map.put("id",1);map.put("tableName","employee");Employee employee = employeeMapper.findByMap(map);System.out.println("employee = " + employee);}
}
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
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;public interface EmployeeMapper {int addEmp(Employee employee);
}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><insert id="addEmp" useGeneratedKeys="true" keyProperty="id" parameterType="com.xuguoguo.domain.Employee"><selectKey>SELECT employee_seq.nextval FROM dual</selectKey>INSERT INTO employee (id,last_name,email,gender)<!--在Oracle数据库中,如果是null值,需要设置jdbcType=NULL-->VALUES (#{id,jdbcType=INTEGER},#{lastName,jdbcType=VARCHAR},#{email,jdbcType=NULL},#{gender,jdbcType=VARCHAR})</insert>
</mapper>
第五章:select 元素
5.1 概述
- select 元素用于定义查询操作。
- id:唯一标识符。用来引用这条语句,需要和接口的方法名一致。
- parameterType:参数类型。可以不传,Mybatis 会根据 TypeHandler 自动推断。
- resultType:返回值类型。别名或者全类名,如果返回的是集合,定义集合中元素的类型。不能和 resultMap 同时使用。
- resultMap:实现高级结果集映射。不能和 resultType 一起使用。
5.2 resultType
5.2.1 返回 List
-
对于 resultType 来说,如果返回的是一个集合,需要写集合中的类型。
-
示例:
-
EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;import java.util.List;public interface EmployeeMapper {List<Employee> findByGender(String gender);
}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><!--resultType:如果返回的是一个集合,需要写集合里面的类型--><select id="findByGender" resultType="com.xuguoguo.domain.Employee">SELECT * FROM employeeWHERE gender = #{gender,jdbcType=VARCHAR}</select></mapper>
5.2.2 返回 Map
-
返回一条记录封装 Map ,key 就是列名,值就是对应的值。
-
示例:
-
EmployeeMapper.java
package com.xuguoguo.mapper;import java.util.Map;public interface EmployeeMapper {Map<String, Object> findById(Integer id);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findById" resultType="java.util.Map">SELECT * FROM employeeWHERE id = #{id,jdbcType=INTEGER}</select></mapper>
-
返回多条记录将其封装为 Map<主键类型,对象类型>,key 是这条记录的主键,值是这条记录。
-
示例:
-
EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;
import org.apache.ibatis.annotations.MapKey;import java.util.Map;public interface EmployeeMapper {@MapKey("id")Map<Integer, Employee> findById(Integer id);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><select id="findById" resultType="java.util.Map">SELECT id,last_name as lastName,gender,email FROM employeeWHERE id = #{id,jdbcType=INTEGER}</select></mapper>
5.3 resultMap
5.3.1 自定义结果映射规则
- 示例:
- EmplyeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;public interface EmployeeMapper {Employee findById(Integer id);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><!--resultMap 自定义关系结果映射规则id:唯一方便引用的idtype:自定义规则的JavaBean类型--><resultMap id="emp" type="com.xuguoguo.domain.Employee"><!--id:指定主键列的封装规则column:指定哪一列property:指定column对应的JavaBean属性--><id property="id" column="id"/><!--result:定义普通列的封装规则column:指定哪一列property:指定column对应的JavaBean属性--><result property="lastName" column="last_name"/><!-- 其它不指定的列会自动封装 --><result property="email" column="email"/><result property="gender" column="gender"/></resultMap><select id="findById" resultMap="emp">SELECT * FROM employeeWHERE id = #{id,jdbcType=INTEGER}</select></mapper>
5.3.2 关联查询
5.3.2.1 环境搭建
- SQL 脚本:
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;INSERT INTO `department` VALUES (1, '开发部');
INSERT INTO `department` VALUES (2, '测试部');DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (`id` int(11) NOT NULL AUTO_INCREMENT,`last_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`department_id` int(11) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE,INDEX `fk_department_id`(`department_id`) USING BTREE,CONSTRAINT `fk_department_id` FOREIGN KEY (`department_id`) REFERENCES `department` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;INSERT INTO `employee` VALUES (1, 'tom', '男', 'tom@qq.com', 1);
INSERT INTO `employee` VALUES (2, 'aa', '女', NULL, 2);
5.3.2.2 级联属性封装查询结果
- 示例:查询一个员工信息以及其所在部门信息
- Department.java
package com.xuguoguo.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;}@Overridepublic String toString() {return "Department{" +"id=" + id +", name='" + name + '\'' +'}';}
}
- Employee.java
package com.xuguoguo.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;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", lastName='" + lastName + '\'' +", email='" + email + '\'' +", gender='" + gender + '\'' +", department=" + department +'}';}
}
- EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;public interface EmployeeMapper {Employee findEmpAndDeptById(Integer id);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><resultMap id="emp" type="com.xuguoguo.domain.Employee"><id property="id" column="id"/><result property="lastName" column="last_name"/><result property="email" column="email"/><result property="gender" column="gender"/><result property="department.id" column="did"/><result property="department.name" column="dept_name"/></resultMap><select id="findEmpAndDeptById" resultMap="emp">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_nameFROM employee e INNER JOIN department dON e.department_id = d.idWHERE e.id = #{id,jdbcType=INTEGER}</select></mapper>
5.3.2.3 association 定义关联对象
- 示例:查询一个员工信息以及其所在部门信息
- Department.java
package com.xuguoguo.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;}@Overridepublic String toString() {return "Department{" +"id=" + id +", name='" + name + '\'' +'}';}
}
- Employee.java
package com.xuguoguo.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;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", lastName='" + lastName + '\'' +", email='" + email + '\'' +", gender='" + gender + '\'' +", department=" + department +'}';}
}
- EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;public interface EmployeeMapper {Employee findEmpAndDeptById(Integer id);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><resultMap id="emp" type="com.xuguoguo.domain.Employee"><id property="id" column="id"/><result property="lastName" column="last_name"/><result property="email" column="email"/><result property="gender" column="gender"/><!--association:可以指定联合的JavaBean对象property:指定哪个属性是联合的对象javaType:指定联合对象的类型--><association property="department" javaType="com.xuguoguo.domain.Department"><id property="id" column="did"/><id property="name" column="dept_name"/></association></resultMap><select id="findEmpAndDeptById" resultMap="emp">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_nameFROM employee e INNER JOIN department dON e.department_id = d.idWHERE e.id = #{id,jdbcType=INTEGER}</select>
</mapper>
5.3.2.4 association 分步查询
- 示例:查询一个员工信息以及其所在部门信息
- Department.java
package com.xuguoguo.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;}@Overridepublic String toString() {return "Department{" +"id=" + id +", name='" + name + '\'' +'}';}
}
- Employee.java
package com.xuguoguo.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;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", lastName='" + lastName + '\'' +", email='" + email + '\'' +", gender='" + gender + '\'' +", department=" + department +'}';}
}
- DepartmentMapper.java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.DepartmentMapper"><select id="findById" resultType="com.xuguoguo.domain.Department">SELECT *FROM departmentWHERE id = #{id,jdbcType=INTEGER}</select>
</mapper>
- EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;public interface EmployeeMapper {Employee findEmpAndDeptById(Integer id);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><resultMap id="emp" type="com.xuguoguo.domain.Employee"><!--分步查询:①按照员工id查询员工信息②根据查询员工信息中的department_id去部门表中查询部门信息③部门设置到员工中--><id property="id" column="id"/><result property="lastName" column="last_name"/><result property="email" column="email"/><result property="gender" column="gender"/><!--association 定义关联对象的封装规则property:关联对象的属性select:表明当前属性是调用select查询的结果column:指定将那一列的值传给这个方法流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的关联对象的属性--><association property="department" select="com.xuguoguo.mapper.DepartmentMapper.findById" column="did" /></resultMap><select id="findEmpAndDeptById" 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 didFROM employee eWHERE e.id = #{id,jdbcType=INTEGER}</select>
</mapper>
分步查询中使用延迟加载:需要在 mybatis-config.xml 中配置如下的全局设置
<settings><!-- 开启自动驼峰命名规则映射 --><setting name="mapUnderscoreToCamelCase" value="true"/><!-- 开启对jdbcType的NULL的支持 --><setting name="jdbcTypeForNull" value="NULL"/><!-- 开启延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 开启按需加载 --><setting name="aggressiveLazyLoading" value="false"/>
</settings>
5.3.2.5 collection 定义关联集合封装规则
- 示例:查询一个部门信息的同时并查询下面的所有员工信息
- Employee.java
package com.xuguoguo.domain;import org.apache.ibatis.type.Alias;@Alias("emp")
public class Employee {private Integer id;private String lastName;private String email;private String gender;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;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", lastName='" + lastName + '\'' +", email='" + email + '\'' +", gender='" + gender + '\'' +'}';}
}
- Department.java
package com.xuguoguo.domain;import java.util.List;public class Department {private Integer id;private String name;private List<Employee> employees;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;}public List<Employee> getEmployees() {return employees;}public void setEmployees(List<Employee> employees) {this.employees = employees;}@Overridepublic String toString() {return "Department{" +"id=" + id +", name='" + name + '\'' +", employees=" + employees +'}';}
}
- DepartmentMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Department;public interface DepartmentMapper {Department findById(Integer id);}
- DepartmentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.DepartmentMapper"><resultMap id="dept" type="com.xuguoguo.domain.Department"><id property="id" column="id"/><result property="name" column="name"/><!--collection 定义关联集合类型的属性的封装规则ofType 定义集合中元素的类型--><collection property="employees" ofType="com.xuguoguo.domain.Employee"><!-- 定义这个集合中元素的封装规则 --><id property="id" column="eid"/><result property="lastName" column="lastName"/><result property="gender" column="gender"/><result property="email" column="email"/></collection></resultMap><select id="findById" resultMap="dept">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 genderFROM department dINNER JOIN employee eON d.id = e.department_idWHERE d.id = #{id,jdbcType=INTEGER}</select>
</mapper>
5.3.2.6 collection 定义分步查询
- 示例:查询一个部门信息的同时并查询下面的所有员工信息
- Employee.java
package com.xuguoguo.domain;import org.apache.ibatis.type.Alias;@Alias("emp")
public class Employee {private Integer id;private String lastName;private String email;private String gender;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;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", lastName='" + lastName + '\'' +", email='" + email + '\'' +", gender='" + gender + '\'' +'}';}
}
- Department.java
```java
package com.xuguoguo.domain;import java.util.List;public class Department {private Integer id;private String name;private List<Employee> employees;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;}public List<Employee> getEmployees() {return employees;}public void setEmployees(List<Employee> employees) {this.employees = employees;}@Overridepublic String toString() {return "Department{" +"id=" + id +", name='" + name + '\'' +", employees=" + employees +'}';}
}
- EmployeeMapper.java```java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;import java.util.List;public interface EmployeeMapper {List<Employee> findByDepatmentId(Integer departmentId);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><resultMap id="emp" type="com.xuguoguo.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 didFROM employee eWHERE e.department_id = #{departmentId,jdbcType=INTEGER}</select>
</mapper>
- DepartmentMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Department;public interface DepartmentMapper {Department findById(Integer id);}
- DepartmentMapper.xml
package com.xuguoguo.mapper;import com.xuguoguo.domain.Department;public interface DepartmentMapper {Department findById(Integer id);}
- DepartmentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.DepartmentMapper"><resultMap id="dept" type="com.xuguoguo.domain.Department"><id property="id" column="id"/><result property="name" column="name"/><collection property="employees" select="com.xuguoguo.mapper.EmployeeMapper.findByDepatmentId" column="{id}"></collection></resultMap><select id="findById" resultMap="dept">SELECT d.id as id,d.name as nameFROM department dWHERE 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 mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.DepartmentMapper"><resultMap id="dept" type="com.xuguoguo.domain.Department"><id property="id" column="id"/><result property="name" column="name"/><collection property="employees" select="com.xuguoguo.mapper.EmployeeMapper.findByDepatmentId" column="{departmentId=id}"></collection></resultMap><select id="findById" resultMap="dept">SELECT d.id as id,d.name as nameFROM department dWHERE 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.xuguoguo.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;}@Overridepublic String toString() {return "Department{" +"id=" + id +", name='" + name + '\'' +'}';}
}
- Employee.java
package com.xuguoguo.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;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", lastName='" + lastName + '\'' +", email='" + email + '\'' +", gender='" + gender + '\'' +", department=" + department +'}';}
}
- DepartmentMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Department;public interface DepartmentMapper {Department findById(Integer id);}
- DepartmentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.DepartmentMapper"><resultMap id="dept" type="com.xuguoguo.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 nameFROM department dWHERE d.id = #{id,jdbcType=INTEGER}</select>
</mapper>
- EmployeeMapper.java
package com.xuguoguo.mapper;import com.xuguoguo.domain.Employee;public interface EmployeeMapper {Employee findById(Integer id);}
- EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuguoguo.mapper.EmployeeMapper"><resultMap id="emp" type="com.xuguoguo.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.xuguoguo.domain.Employee"><association property="department" javaType="java.lang.Integer" select="com.xuguoguo.mapper.DepartmentMapper.findById" column="did"/></case><case value="男" resultType="com.xuguoguo.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 didFROM employee eWHERE e.department_id = #{departmentId,jdbcType=INTEGER}</select>
</mapper>
小结
提示:本章节中主体摘录了对Mybatis持久层框架技术的配置文件的编写摘录,!
多学一招,偷偷的努力,然后惊艳所有人!!!卷就完了……
本小节完毕,敬请期待后续更新(可留言需要学习哪方面的内容哈)!如果需要源码或者工具的朋友们可关注微信公众号"锅锅编程生活"或者扫描二维码关注回复关键字/后台留言获取即可!`