基础组件
SqlSessionFactory
初始化
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
绑定配置文件初始化sqlSessionFactory
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
实例化 xml 文件解析类
parser.parse();使用该方法解析标签,返回Configuration
最终
return new DefaultSqlSessionFactory(config);
自此SqlSessionFactory 初始化结束
SqlSession
初始化
SqlSession sqlsession = sqlSessionFactory.openSession();
//Environment 类,包含数据源以及事务工厂
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//工厂模式初始化事务类,包含 数据源,隔离级别,自动提交
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//初始化执行器
final Executor executor = configuration.newExecutor(tx, execType);
主要分为3类
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
//将拦截器链加入到执行器
executor = (Executor) interceptorChain.pluginAll(executor);
//返回sqlsession
return new DefaultSqlSession(configuration, executor, autoCommit);
<T>Mapper
//获取mapper代理类
drawMapper = sqlsession.getMapper(DrawMapper.class);
public <T> T getMapper(Class<T> type) {
return configuration.<T>getMapper(type, this);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
return mapperProxyFactory.newInstance(sqlSession);
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
最终返回代理类
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
该代理方式为jdbc 动态代理,代理增强逻辑为mapperProxy
调用mapper接口会直接路由到mapperProxy中的invoke函数中
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
最终进入jdbc 或者数据库连接池
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
Interceptor
拦截器工作原理
在xml中注册拦截器后,在XMLConfigBuilder中的 pluginElement()组件会解析拦截器并反射创建实例
拦截器被添加到 Configuration 对象的拦截器链中
在创建 Executor、StatementHandler、ParameterHandler 和 ResultSetHandler 时会使用 Plugin.wrap() 方法为这些对象创建代理
这些对象被创建时,会通过 InterceptorChain.pluginAll() 方法将所有配置的拦截器应用到目标对象上,形成代理链。
基础使用
mybatis-config.xml
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 数据库相关属性文件,这里不写的话,会自动加载 config.properties -->
<properties resource="db.properties"></properties>
<typeAliases>
<typeAlias type="DruidDataSourceFactory"
alias="DRUID" />
</typeAliases>
<!-- <typeAliases>-->
<!-- <typeAlias type="c3p0DataSourceFactory"-->
<!-- alias="C3P0" />-->
<!-- </typeAliases>-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
</plugin>
</plugins>
<!-- 环境配置 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!-- 数据库连接相关配置 ,这里动态获取config.properties文件中的内容-->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
<!-- <dataSource type="C3P0">-->
<!-- <property name="driverClass" value="${driver}"/>-->
<!-- <property name="jdbcUrl" value="${url}"/>-->
<!-- <property name="user" value="${username}"/>-->
<!-- <property name="password" value="${password}"/>-->
<!-- </dataSource>-->
</environment>
</environments>
<mappers>
<mapper resource="Mapper/DrawMapper.xml"/>
</mappers>
</configuration>
mapper.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="DrawMapper">
<update id="mergeInto" parameterType="java.util.List">
MERGE INTO DRAW t
USING (
<foreach collection="list" item="record" separator="UNION ALL">
SELECT
#{record.metid} AS METID,
#{record.datatime} AS DATATIME,
#{record.remark} AS REMARK
FROM DUAL
</foreach>
) s
ON (t.METID = s.METID)
WHEN MATCHED THEN
UPDATE SET
t.REMARK = s.REMARK
WHEN NOT MATCHED THEN
INSERT (METID, DATATIME,REMARK)
VALUES (s.METID, s.DATATIME,s.REMARK)
</update>
<!-- <insert id="testinsert" parameterType="Draw">-->
<!-- insert into draw(metid,datatime,remark) values-->
<!-- (#{metid},#{datatime},#{remark})-->
<!-- </insert>-->
<insert id="testinsert" >
insert into draw(metid,datatime,remark)
select * from (
<foreach collection="list" item="item" separator=" union all ">
SELECT
#{item.metid},#{item.datatime},#{item.remark}
FROM dual
</foreach>
)
</insert>
<insert id="foreachadd" >
<foreach collection="list" item="item">
insert into draw(metid,datatime,remark) values
(#{item.metid},#{item.datatime},#{item.remark});
</foreach>
</insert>
<select id="getAll" resultType="Draw">
select * from draw
</select>
</mapper>
基础使用
public class test {
private static SqlSessionFactory sf;
private static SqlSession sqlsession;
private static DrawMapper drawMapper;
static String resource = "mybatis-config.xml";
public static void main(String[] args) throws Exception{
List list = new ArrayList();
for(int i=0;i<1;i++){
list.add(new Draw(i,"2022-01-01 12:00:00", UUID.randomUUID().toString()));
}
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlsession = sqlSessionFactory.openSession();
drawMapper = sqlsession.getMapper(DrawMapper.class);
System.out.println("i= " + i);
drawMapper.mergeInto(list);
sqlsession.commit();
sqlsession.close();
}
}