mybatis
1.依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
在classpath下建立log4j.properties
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="on" monitorInterval="1800">
<!-- <properties>-->
<!-- <property name="LOG_HOME">/opt/logs/hafiz/log4j2Demo/logs</property>-->
<!-- <property name="ERROR_LOG_FILE_NAME">error</property>-->
<!-- </properties>-->
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p (%F:%L) - %m%n"/>
</Console>
<!-- <RollingRandomAccessFile name="ErrorLog"-->
<!-- fileName="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log"-->
<!-- filePattern="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log.%d{yyyy-MM-dd}.gz">-->
<!-- <PatternLayout-->
<!-- pattern="%d %-5p (%F:%L) - %m%n"/>-->
<!-- <Policies>-->
<!-- <TimeBasedTriggeringPolicy/>-->
<!-- <SizeBasedTriggeringPolicy size="100 MB"/>-->
<!-- </Policies>-->
<!-- <DefaultRolloverStrategy max="20"/>-->
<!-- </RollingRandomAccessFile>-->
</Appenders>
<Loggers>
<!-- 3rdparty Loggers -->
<!-- <logger name="org.springframework.core" level="info">-->
<!-- </logger>-->
<!-- <logger name="org.springframework.beans" level="info">-->
<!-- </logger>-->
<!-- <logger name="org.springframework.context" level="info">-->
<!-- </logger>-->
<!-- <logger name="org.springframework.web" level="info">-->
<!-- </logger>-->
<!-- <logger name="com.hafiz.www.controller" level="info" includeLocation="true" additivity="false">-->
<!-- <appender-ref ref="ErrorLog"/>-->
<!-- <appender-ref ref="Console"/>-->
<!-- </logger>-->
<root level="DEBUG" includeLocation="true">
<appender-ref ref="Console"/>
</root>
</Loggers>
</Configuration>
2.测试
2.1.项目结构:

2.2.具体内容
(1)测试类:
public class MyBatisTest {
@Test
public void test() {
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取sqlSession实例,能够执行已经映射的sql语句
SqlSession sqlSession = sqlSessionFactory.openSession();
Employee employee = (Employee) sqlSession.selectOne("mybatis.mapper.EmpMapper.selectEmp", 1);
System.out.println(employee);
}
}
(2)mybatis全局配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="EmployeeMapper.xml"/>
</mappers>
</configuration>
(3)xxxMapper.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="mybatis.mapper.EmpMapper">
<select id="selectEmp" resultType="mybatis.bean.Employee">
select *
from tbl_employee
where id = #{id}
</select>
</mapper>
- 程序会根据全局配置文件得到SqlSessionFactory
- 使用SqlSessionFactory工厂,获取到sqlSession对象并使用其进行增删改查,一个sqlSession就是代表和数据库的一次会话,用完即关闭
- 使用sql的唯一标志来告诉MyBatis执行哪个sql,且sql均是保存在sql映射文件中
openSession方法中可以传参,用于标识是否自动提交,默认不是自动提交
数据库中字段与实体类中属性名不一致时(包括实体类使用驼峰,而数据库中使用下划线致使不一致的情况),可以使用在sql中起别名的方式来避免此问题的发生
3.接口式编程(推荐)
xxxMapper.xml中namespace需要指定为对应mapper接口的全类名,且配置语句中的id应改为接口中对应的方法名
测试类:
public class MyBatisTest {
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test() throws IOException {
SqlSession sqlSession = getSqlSessionFactory().openSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
System.out.println(empMapper.getEmployeeById(1));
}
}
4.MyBatis全局配置扩展
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--myBatis可以使用properties来引入外部properties配置文件的内容-->
<!--resource可以引入类路径下资源-->
<!--url可以引入网络路径或者磁盘路径下的资源-->
<properties resource="dbconfig.properties"></properties>
<!--设置驼峰命名策略(实体类属性用驼峰,数据库字段用下划线)-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--起别名,使得写全类名的地方可以直接写类名,简化操作-->
<typeAliases>
<!--默认别名为类名小写-->
<typeAlias type="mybatis.bean.Employee" alias="emp"></typeAlias>
<!--package默认为每个包批量起别名(为当前包以及下面所有的后代包的每一个类都起一个默认别名(类名小写,且别名不区分大小写))-->
<package name="mybatis"/>
</typeAliases>
<!--可以配置多种环境-->
<!--environment用于配置一个具体环境,且必须有transactionManager和dataSource标签-->
<!--利用default属性更换环境-->
<!--transactionManager的type属性有两种取值:1.JDBC(JdbcTransactionFactory.class) 2.MANAGED(ManagedTransactionFactory.class)-->
<!--自定义事务管理器:实现TransactionFactory接口-->
<!--dataSource有两种取值:1.UNPOOLED 2.POOLED 3.JNDI-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--支持多数据库厂商 DB_VENDOR(VendorDatabaseIdProvider.class) 作用是得到数据库厂商的标识(驱动自带的 JDBC接口中存在getDatabaseProductName),mybatis能够根据数据库厂商标识执行不同的sql-->
<!--标识:MySQL Orace SQL Server-->
<databaseIdProvider type="DB_VENDOR">
<!--为不同数据库厂商起别名-->
<!--之后在mapper.xml中select标签的databaseId属性中配置所起的别名,用于标识该条sql在什么环境下使用-->
<!--不同数据库环境下的一条sql,所编写的两个select标签相同,只是databaseId不同-->
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
<property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>
<!--将sql映射注册到全局配置中-->
<!--注解配置文件:-->
<!--1.resource用于指定类路径下的映射文件-->
<!--2.url用于引用网络/磁盘路径下的映射文件-->
<!--注册接口:-->
<!--1.class用于引用接口(写接口全类名),使用此种方法,要求映射文件名和接口同名,且需要在一个包下,如果没有映射文件,则使用注解将sql写在接口上-->
<mappers>
<mapper resource="EmployeeMapper.xml"/>
</mappers>
</configuration>
也可以使用注解配置别名(注解优先于配置文件生效):
/*使用注解配置别名*/
@Alias("emp")
public class Employee
MyBatis内置别名:

在接口上写注解:
public interface EmpMapper {
@Select("select * from tbl_employee where id = #{id}")
public Employee getEmployeeById(Integer id);
}
5.增删改查方法
xxxMapper.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="mybatis.dao.EmpMapper">
<select id="getEmployeeById" resultType="emp">
select *
from tbl_employee
where id = #{id}
</select>
<insert id="addEmp">
insert into tbl_employee(last_name, gender, email)
values (#{lastName}, #{gender}, #{email})
</insert>
<update id="updateEmp">
update tbl_employee
set last_name=#{lastName},
gender=#{gender},
email=#{email}
where id = #{id}
</update>
<delete id="deleteEmpById">
delete
from tbl_employee
where id = #{id}
</delete>
</mapper>
测试类:
import mybatis.dao.EmpMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisTest {
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test() {
SqlSession sqlSession = null;
try {
sqlSession = getSqlSessionFactory().openSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
System.out.println(empMapper.getEmployeeById(1));
// Employee employee = new Employee(null,"Jerry", "123@qq.com", "男");
// empMapper.addEmp(employee);
// Employee employee = new Employee(2, "Tom", "123@qq.com", "男");
// empMapper.updateEmp(employee);
// empMapper.deleteEmpById(2);
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
}
MyBatis允许增删改直接定义以下返回值:1.Integer 2.Long 3.Boolean,且在update/insert/delete标签内不能写resultType
6.获取insert时的自增主键值
6.1.MySQL
MySql支持自增主键,关于自增主键的获取,可以使用statement.getGeneratedKeys()
在xxxMapper.xml文件中添加useGeneratedKeys属性,使用自增主键获取主键值策略,同时设置keyProperty属性,用于指明此值赋值给javaBean的哪个属性
<insert id="addEmp" useGeneratedKeys="true" keyProperty="id">
insert into tbl_employee(last_name, gender, email)
values (#{lastName}, #{gender}, #{email})
</insert>
测试类:
import mybatis.bean.Employee;
import mybatis.dao.EmpMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisTest {
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test() {
SqlSession sqlSession = null;
try {
sqlSession = getSqlSessionFactory().openSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
System.out.println(empMapper.getEmployeeById(1));
Employee employee = new Employee(null, "Jerry", "123@qq.com", "男");
empMapper.addEmp(employee);
System.out.println(employee.getId()); // 返回插入词条数据时的主键值
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
}
6.2.Oracle
Oracle不支持自增,其使用序列来模拟自增
每次插入的数据的主键是从序列中拿到的值
使用命令select * from user_sequences;可以查看所有的序列
使用select 序列名.nextval from dual;可以查询序列的值
(1)导入Oracle依赖:
<dependency>
<groupId>cn.easyproject</groupId>
<artifactId>orai18n</artifactId>
<version>12.1.0.2.0</version>
</dependency>
<!--解决乱码问题-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
(2)属性配置文件添加oracle相关连接属性:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
orcl.driver=oracle.jdbc.OracleDriver
orcl.url=jdbc:oracle:thin:@192.168.88.135:1521:orcl
orcl.username=scott
orcl.password=scott
(3)切换配置(修改environments标签的default属性):
<environments default="oracle">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
<environment id="oracle">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${orcl.driver}"/>
<property name="url" value="${orcl.url}"/>
<property name="username" value="${orcl.username}"/>
<property name="password" value="${orcl.password}"/>
</dataSource>
</environment>
</environments>
(4)xxxMapper.xml配置文件:
其会根据连接字符串识别出当前数据库环境,查找到配置文件中相匹配的sql语句
<insert id="addEmp" useGeneratedKeys="true" keyProperty="id" databaseId="mysql">
insert into tbl_employee(last_name, gender, email)
values (#{lastName}, #{gender}, #{email})
</insert>
<insert id="addEmp" databaseId="oracle">
/*BEFORE表示在sql执行之前调用 resultType表示查询数据的类型 keyProperty表示查询出的值赋给javaBean的哪个类型*/
<selectKey keyProperty="id" order="BEFORE" resultType="int">
select emp_seq.nextval from dual
</selectKey>
insert into emp(empno, ename)
values (#{id}, #{lastName})
</insert>
(5)测试类:
import mybatis.bean.Employee;
import mybatis.dao.EmpMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisTest {
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test() {
SqlSession sqlSession = null;
try {
sqlSession = getSqlSessionFactory().openSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
Employee employee = new Employee(null, "Jerry", "123@qq.com", "男");
empMapper.addEmp(employee);
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
}
7.MyBatis参数处理
- 使用单个参数,MyBatis不会做特殊处理,使用
#{参数名}即可取出参数值,因为只有一个参数,参数名可以任意起,无需和形参名称一致 - 使用多个参数,参数会被封装成一个Map(key为
param1到paramN或者arg0到argM,value为传入的参数值),因此需要使用类似#{arg0}或者#{param1}的方式获取参数值

- 使用多个参数时,也可以在接口方法参数上使用
@param设置参数名(即使用命名参数的方式),如:public Employee getEmployeeByIdAndName(@Param("id") Integer id, @Param("lastName") String lastName);,此时sql语句中直接使用#{id}、#{lastName}即可获取参数值 - 如果多个参数是业务逻辑的数据模型的属性,则参数可直接使用
POJO类型,使用#{类型属性名}即可获取参数值 - 如果多个参数没有
POJO类型相匹配,则参数可使用Map,利用#{Map中属性值}即可获取参数值 - 如果多个参数虽然不是业务模型中数据,但是要经常使用,推荐编写一个
TO(Transfer Object,数据传输对象),如class Page{int index;int size;}
7.1.实例
(1)public Employee getEmployeeByIdAndName(@Param("id") Integer id, String lastName),取值id=>#{id/param1}、lastName=>#{param2}
(2)public Employee getEmployeeByIdAndName(@Param("id") Integer id, @Param("e") Employee e),取值id=>#{param1}、lastName=>#{param2.lastName/e.lastName}
如果是Collection(List/Set)类型或者数组,也会特殊处理,也是把传入的list或者数组封装在map中,其中key为collection,如果是List,key也可以为list,如果是数组,则key为array
(3)public Employee getEmployees(List<Integer> ids),取出第一个id的值#{collection[0]}或者#{list[0]}
8.#{}与${}区别
二者均可以获取Map或者POJO中的值,但是#{}是以预编译的形式,将参数设置到sql语句中,类似原生JDBC使用PreparedStatement,能够防止sql注入,而${}是将取出的值直接拼装在sql语句中,存在安全问题
原生JDBC不支持占位符的地方就可以使用${}进行取值
大多情况下取参数的值都应该使用#{},但是对于分表操作(如按照年份分表拆分)select * from ${表名}
8.1.#{}丰富用法
参数可以指定特殊的数据类型,如#{property,javaType=int,jdbcType=NUMERIC}
(1)jdbcType通常需要在某种特定情况下被设置:
在数据为null时,有些数据库不能识别mybatis对null的默认处理,如Oracle在新增数据时传入null

错误原因:MyBatis对所有的null映射的都是JDBC OTHER类型,Oracle不能正确处理
- 解决方式一:设置JdbcType为null
<insert id="addEmp" databaseId="oracle">
/*BEFORE表示在sql执行之前调用 resultType表示查询数据的类型 keyProperty表示查询出的值赋给javaBean的哪个类型*/
<selectKey keyProperty="id" order="BEFORE" resultType="int">
select emp_seq.nextval from dual
</selectKey>
insert into emp(empno, ename)
values (#{id}, #{lastName,jdbcType=NULL})
</insert>
- 解决方式二:
在全局配置文件中进行修改:
<settings>
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>
9.select标签
9.1.resultType
(1)如果返回list,则resultType写集合内的元素类型,如:
<select id="getEmployeeList" resultType="emp">
select *
from tbl_employee
</select>
(2)如果返回标识为一个对象的Map(即Map对应一个实体对象),key为列名,值为对应的值,resultType为map
<select id="getEmployeeById" resultType="map">
select *
from tbl_employee
where id = #{id}
</select>
(3)如果返回多条记录封装成的Map,如Map<String,Employee>
Mapper接口:
public interface EmpMapper {
// 标识map的key为id属性
@MapKey("id")
public Map<String, Employee> getEmployeeList();
}
配置文件:
<select id="getEmployeeList" resultType="emp">
select *
from tbl_employee
</select>
9.2.resultMap
此属性用于自定义结果集
9.2.1.定义普通对象映射规则:
<mapper namespace="mybatis.dao.EmployeeMapperPlus">
<select id="getEmpById" resultMap="myEmp">
select *
from tbl_employee
where id = #{id}
</select>
<!--自定义javaBean的封装规则-->
<!--type为自定义的Java类型 id自定义,唯一id便于引用-->
<!--id标签用于定义主键,底层有优化 result标签用于定义普通属性-->
<resultMap id="myEmp" type="emp">
<id column="id" property="id"></id>
<result column="last_name" property="lastName"></result>
<result column="gender" property="gender"></result>
<result column="email" property="email"></result>
</resultMap>
</mapper>
9.2.2.级联查询
(1)使用级联属性
<select id="getEmployeeAndDept" resultMap="myDifEmp">
select e.id id, e.last_name last_name, e.gender gender, d.id did, d.dept_name dept_name
from tbl_employee e
left join tbl_dept d on e.dept_id = d.id
where e.id = #{id}
</select>
<!--联合查询,使用级联属性封装-->
<resultMap id="myDifEmp" type="emp">
<id property="id" column="id"></id>
<result property="lastName" column="last_name"></result>
<result column="gender" property="gender"></result>
<result column="email" property="email"></result>
<result column="did" property="dept.id"></result>
<result column="dept_name" property="dept.deptName"></result>
</resultMap>
(2)使用association标签
<select id="getEmployeeAndDept" resultMap="myDifEmp">
select e.id id, e.last_name last_name, e.gender gender, d.id did, d.dept_name dept_name
from tbl_employee e
left join tbl_dept d on e.dept_id = d.id
where e.id = #{id}
</select>
<resultMap id="myDifEmp" type="emp">
<id property="id" column="id"></id>
<result property="lastName" column="last_name"></result>
<result column="gender" property="gender"></result>
<result column="email" property="email"></result>
<!--association标签可用于在指定联合的javaBean对象 property属性用于指定哪个属性是联合的对象 javaType属性指定属性对象的类型(此处不可省)-->
<association property="dept" javaType="dept">
<id property="id" column="did"></id>
<result property="deptName" column="dept_name"></result>
</association>
</resultMap>
(3)使用association进行分步查询
<select id="getEmpByIdStep" resultMap="MyEmpByStep">
select *
from tbl_employee
where id = #{id}
</select>
<resultMap id="MyEmpByStep" type="emp">
<id column="id" property="id"></id>
<result column="last_name" property="lastName"></result>
<result column="gender" property="gender"></result>
<result column="email" property="email"></result>
<!--select属性表明当前属性是调用select指定的方法查出的结果 column指指定将哪一列的值传给这个方法-->
<!--流程:使用select指定的方法(传入column指定的此列参数的值),并封装给对应的property属性-->
<association property="dept" select="mybatis.dao.DepartmentMapper.getDepartmentById" column="dept_id">
<id column="id" property="id"></id>
<result column="dept_name" property="deptName"></result>
</association>
</resultMap>
(4)延迟加载(在分布查询基础上)
可以在分布查询的基础上,使用延迟加载,如果部门信息在使用时再去查询,则能够有效节省资源
在全局配置上配置两个属性,即可开启此功能
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
测试代码:(只获取员工相关属性信息时,不会查询部门表)
EmployeeMapperPlus employeeMapperPlus = sqlSession.getMapper(EmployeeMapperPlus.class);
Employee employee = employeeMapperPlus.getEmpByIdStep(1);
System.out.println(employee.getLastName());

(5)collection关联集合
<select id="getDepartmentByIdPlus" resultMap="MyDept">
select d.id did, d.dept_name dept_name, e.id eid, e.last_name last_name, e.email email, e.gender gender
from tbl_dept d
left join tbl_employee e
on d.id = e.dept_id
where d.id = #{id}
</select>
<resultMap id="MyDept" type="dept">
<id column="did" property="id"></id>
<result column="dept_name" property="deptName"></result>
<!--ofType指定集合内元素类型-->
<collection property="emps" ofType="emp">
<id property="id" column="id"></id>
<result property="lastName" column="last_name"></result>
<result column="gender" property="gender"></result>
<result column="email" property="email"></result>
</collection>
</resultMap>
(6)collection关联集合分步查询
<select id="getDepartmentByIdStep" resultMap="MyDeptMap">
select *
from tbl_dept
where id = #{id}
</select>
<resultMap id="MyDeptMap" type="dept">
<id column="did" property="id"></id>
<result column="dept_name" property="deptName"></result>
<collection property="emps" ofType="emp" select="mybatis.dao.EmployeeMapperPlus.getEmpByDeptId" column="id">
<id column="id" property="id"></id>
<result column="last_name" property="lastName"></result>
<result column="gender" property="gender"></result>
<result column="email" property="email"></result>
</collection>
</resultMap>
如果要传递多列值,则可以将多列值封装成map,如column={key=columnName1,key=columnName2}的方式
<collection property="emps" ofType="emp" select="mybatis.dao.EmployeeMapperPlus.getEmpByDeptId" column="{id=id}">
<id column="id" property="id"></id>
<result column="last_name" property="lastName"></result>
<result column="gender" property="gender"></result>
<result column="email" property="email"></result>
</collection>
collection标签中存在fetchType属性,其可以取两个值lazy(延迟)与eager(立即),表示是否使用延迟加载,可以在此设置为eager以禁用全局的延迟加载
(7)collection关联集合分步查询
<resultMap id="empDis" type="emp">
<id column="id" property="id"></id>
<result column="last_name" property="lastName"></result>
<result column="gender" property="gender"></result>
<result column="email" property="email"></result>
<!--MyBatis可以使用鉴别器discriminator判断某列的值,之后根据某列的值改变封装行为-->
<!--javaType为列值对应的java类型 column指定判断的列名-->
<discriminator javaType="string" column="gender">
<case value="0" resultType="emp">
<association property="dept" select="mybatis.dao.DepartmentMapper.getDepartmentById" column="dept_id">
<id column="id" property="id"></id>
<result column="dept_name" property="deptName"></result>
</association>
</case>
<!--注意此处resultType/resultMap不能省-->
<case value="1" resultType="emp">
<id column="id" property="id"></id>
<result column="last_name" property="lastName"></result>
<result column="gender" property="gender"></result>
<result column="last_name" property="email"></result>
</case>
</discriminator>
</resultMap>
10.动态SQL
<select id="getEmpsByConditionIf" resultType="emp">
select *
from tbl_employee
<where>
/*test中使用OGNL表达式*/
<if test="id!=null">
id=#{id}
</if>
/*遇见特殊符号写转义字符 如&写成& "写成"*/
<if test="lastName!=null or lastName !=''">
and last_name like #{lastName}
</if>
<if test="email!=null or email.trim() != ''">
and email = #{email}
</if>
/*OGNL会自动进行字符串与数字的转换判断*/
<if test="gender==0 or gender==1">
and gender = #{gender}
</if>
</where>
</select>

浙公网安备 33010602011771号