1. Mybatis逆向工程
1.1 说明
MyBatis Generator官方文档地址
依赖的包
1
2
3
4
5
6
7
8
9
10
11<!--mybatis逆向工程依赖包-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
</dependency>1.2 逆向功能的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime="MyBatis3Simple":生成简单版的CRUD
MyBatis3:豪华版
-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!-- jdbcConnection:指定如何连接到目标数据库 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis?allowMultiQueries=true"
userId="root"
password="123456">
</jdbcConnection>
<!-- -->
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- javaModelGenerator:指定javaBean的生成策略
targetPackage="test.model":目标包名
targetProject="\MBGTestProject\src":目标工程
-->
<javaModelGenerator targetPackage="com.atguigu.mybatis.bean"
targetProject=".\src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- sqlMapGenerator:sql映射生成策略: -->
<sqlMapGenerator targetPackage="com.atguigu.mybatis.dao"
targetProject=".\conf">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- javaClientGenerator:指定mapper接口所在的位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.atguigu.mybatis.dao"
targetProject=".\src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 指定要逆向分析哪些表:根据表要创建javaBean -->
<table tableName="tbl_dept" domainObjectName="Department"></table>
<table tableName="tbl_employee" domainObjectName="Employee"></table>
</context>
</generatorConfiguration>
2. Mybatis的运行原理
2.1 sqlsessionFactory的初始化
- 根据配置文件创建sqlsessionFactory
- 几个重要的类
2.2 openSession获取SqlSession对象
返回SqlSession的实现类DefaultSqlSession对象。他里面包含了Executor和Configuration;Executor会在这一步被创建
2.3 getMapper获取到接口的代理对象
getMapper返回接口的代理对象包含了SqlSession对象
2.4 查询实现
3.插件
MyBatis在四大对象的创建过程中,都会有插件进行介入。插件可以利用动态代理机制一层层的包装目标对象,而实现在目标对象执行目标方法之前进行拦截的效果。
MyBatis 允许在已映射语句执行过程中的某一点进行拦截调用。
默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
- Executor(update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler(getParameterObject, setParameters)
- ResultSetHandler(handleResultSets, handleOutputParameters)
- StatementHandler(prepare, parameterize, batch, update, query)
3.1 插件开发的步骤
编写插件实现Interceptor接口并使用@Intercepts注解完成插件签名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48package com.atguigu.in;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import java.util.Properties;
/**
* intercept:拦截目标对象的目标方法的执行
* 完成插件的签名:
* 告诉mybatis当前插件来拦截那个执行器的那个方法
*/
@Intercepts({
@Signature(
type = StatementHandler.class,method = "parameterize",args=java.sql.Statement.class
)
})
public class MyFirstIn implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
//放行执行目标方法
Object proceed = invocation.proceed();
return proceed;
}
/**
* 插件包装
* 为目标对象创建一个代理对象
* @param target
* @return
*/
@Override
public Object plugin(Object target) {
Object wrap = Plugin.wrap(target, this);
//我们可以借助Plugin的wrap方法来使用当前的拦截器包装我们的对象
//返回为当前target创建的动态代理
return wrap;
}
/**
* 将插件注册时的properties属性注册出来
* @param properties
*/
@Override
public void setProperties(Properties properties) {
System.out.println("可以拿到插件的信息");
}
}在全局配置文件中注册插件
1
2
3
4
5<plugins>
<plugin interceptor="com.atguigu.in.MyFirstIn">
<property name="name" value="ceshi"/>
</plugin>
</plugins>
4. mybatis批量操作
默认的openSession() 方法没有参数,它会创建有如下特性的
- 会开启一个事务(也就是不自动提交)
- 连接对象会从由活动环境配置的数据源实例得到
- 事务隔离级别将会使用驱动或数据源的默认设置
- 预处理语句不会被复用,也不会批量处理更
openSession 方法的ExecutorType类型的参数,枚举类型:
- ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情(这是默认装配的)。它为每个语句的执行创建一个新的预处理语句
- ExecutorType.REUSE: 这个执行器类型会复用预处理语句
- ExecutorType.BATCH: 这个执行器会批量执行所有更新语句
批量操作我们是使用MyBatis提供的BatchExecutor进行的,他的底层就是通过jdbc攒sql的方式进行的。我们可以让他攒够一定数量后发给数据库一次
1
2
3
4
5
6
7
8
9
10
11
12
13publicvoidtest01() {
SqlSession openSession = build.openSession(ExecutorType.BATCH);
UserDao mapper = openSession.getMapper(UserDao.class);
longstart = System.currentTimeMillis();
for(inti = 0; i < 1000000; i++) {
String name = UUID.randomUUID().toString().substring(0, 5);
mapper.addUser(newUser(null, name, 13));
}
openSession.commit();
openSession.close();
longend = System.currentTimeMillis();
System.out.println("耗时时间:"+(end-start));
}与Spring整合中,我们推荐,额外的配置一个可以专门用来执行批量操作的sqlSession
需要用到批量操作的时候,我们可以注入配置的这个批量SqlSession。通过他获取到mapper映射器进行操作
注意
- 批量操作是在session.commit()以后才发送sql语句给数据库进行执行的
- 如果我们想让其提前执行,以方便后续可能的查询操作获取数据,我们可以使用sqlSession.flushStatements()方法,让其直接冲刷到数据库进行执行
5. 一个带游标的存储过程
MyBatis对存储过程的游标提供了一个JdbcType=CURSOR的支持,可以智能的把游标读取到的数据,映射到我们声明的结果集中
存储过程的调用
select标签中statementType=“CALLABLE”
标签体中调用语法:{call procedure_name(#{param1_info},#{param2_info})}
6.自定义TypeHandler处理枚举
- 我们可以通过自定义TypeHandler的形式来在设置参数或者取出结果集的时候自定义参数封装策略
- 步骤
- 实现TypeHandler接口或者继承BaseTypeHandler
- 使用@MappedTypes定义处理的java类型
- 使用@MappedJdbcTypes定义jdbcType类型
- 在自定义结果集标签或者参数处理的时候声明使用自定义TypeHandler进行处理,或者在全局配置TypeHandler要处理的javaType