一,执行流程图
二,执行步骤分析
1,初始化配置信息,其中包括Mapper初始化
2,openSession(),初始化DefaultSqlSession和Executor执行器
3,getMapper(),获取执行Mapper的代理对象,准备执行Statement
4,执行Statement,通过动态代理执行方法,获取数据库结果集,并映射到JavaBean
三,代码示例
1,整体代码结构
* POM文件
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</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>5.1.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.7.0</version>
</dependency>
2,Mapper接口
package com.gupao.self.text;
import com.gupao.self.pojo.UserVO;
import java.util.List;
/**
* @author pj_zhang
* @create 2019-03-31 11:10
**/
public interface TestMapper {
/**
* 查询结果集
* @return
*/
List<UserVO> selectData();
}
3,客户端执行类
package com.gupao.self.text;
import com.gupao.self.pojo.UserVO;
import com.gupao.self.sqlsession.SelfSqlSession;
import com.gupao.self.sqlsession.SelfSqlSessionFactory;
import com.gupao.self.sqlsession.SelfSqlSessionFactoryBuilder;
import java.util.List;
/**
* @author pj_zhang
* @create 2019-03-31 11:31
**/
public class SelfMybatisTest {
public static void main(String[] args) {
// 获取sqlSessionFactory
SelfSqlSessionFactory sqlSessionFactory = new SelfSqlSessionFactoryBuilder().build();
// 获取sqlSession
SelfSqlSession sqlSession = sqlSessionFactory.openSession();
// 获取mapper
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
// 执行Statement
List<UserVO> lstData = mapper.selectData();
// 输出结果
System.out.println(lstData);
}
}
* VO类
package com.gupao.self.pojo;
import lombok.Data;
/**
* @author pj_zhang
* @create 2019-03-31 11:56
**/
@Data
public class UserVO {
private String name;
private String word;
}
4,初始化配置信息,获取SqlSessionFactory解析
* 通过SqlSessionFactoryBuilder.builder()构建DefaultSqlSessionFactory,传递Configuration对象引用
package com.gupao.self.sqlsession;
import com.gupao.self.config.SelfConfiguration;
import com.gupao.self.config.SelfConfigurationBuilder;
/**
* 自定义SelfSqlSessionFactoryBuilder, 用来构造SqlSessionFactory
* @author pj_zhang
* @create 2019-03-31 10:57
**/
public class SelfSqlSessionFactoryBuilder {
public SelfSqlSessionFactory build() {
// 初始化配置信息, 生成全局配置文件
SelfConfiguration configuration = SelfConfigurationBuilder.createConfiguration();
return new SelfDefaultSqlSessionFactory(configuration);
}
}
* 初始化Configuration对象,并对配置文件进行解析(此处通过硬编码说明问题)
package com.gupao.self.config;
/**
* 全局配置信息构建类
* @author pj_zhang
* @create 2019-03-31 11:02
**/
public class SelfConfigurationBuilder {
/**
* 构建有效的配置信息
* @return
*/
public static SelfConfiguration createConfiguration() {
SelfConfiguration configuration = new SelfConfiguration();
// 解析mapper
resolveMapper(configuration);
return configuration;
}
/**
* 解析Mapper
* @param configuration
*/
private static void resolveMapper(SelfConfiguration configuration) {
try {
configuration.addMapper();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
* Configuration对象内部添加mapper
// 添加mapper
// SelfConfiguration.addMapper
public void addMapper() throws ClassNotFoundException {
selfMapperRegister.addMapper();
}
* 转发SelfMapperRegister添加,添加mapper到Map集合中,后续通过SelfMapperProxyFactory获取代理对象
package com.gupao.self.mapper;
import com.gupao.self.sqlsession.SelfSqlSession;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 自定义Mapper注册类
* @author pj_zhang
* @create 2019-03-31 11:08
**/
public class SelfMapperRegister {
private Map<Class<?>, SelfMapperProxyFactory<?>> knowsMapper = new ConcurrentHashMap<>();
// 添加mapper
// SelfMapperRegister.addMapper
public void addMapper() throws ClassNotFoundException {
knowsMapper.put(Class.forName(SelfMapperMap.NAME_SPACE), new SelfMapperProxyFactory(Class.forName(SelfMapperMap.NAME_SPACE)));
}
public static class SelfMapperMap {
public static final String NAME_SPACE = "com.gupao.self.text.TestMapper";
public static final Map<String, String> statement2Sql = new ConcurrentHashMap<>();
static {
statement2Sql.put("selectData", "select username as name, password as word from user_t");
}
}
}
5,获取SqlSession
* SqlSession触发
// 获取sqlSession
SelfSqlSession sqlSession = sqlSessionFactory.openSession();
* 从SqlSessionFactory获取sqlSession;内部初始化Executor执行器,最终返回DefaultSqlSession
package com.gupao.self.sqlsession;
import com.gupao.self.config.SelfConfiguration;
import com.gupao.self.executor.SelfCachingExecutor;
import com.gupao.self.executor.SelfExecutor;
import com.gupao.self.executor.SelfSimpleExecutor;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
/**
* @author pj_zhang
* @create 2019-03-31 11:00
**/
public class SelfDefaultSqlSessionFactory implements SelfSqlSessionFactory {
private SelfConfiguration configuration;
public SelfDefaultSqlSessionFactory(SelfConfiguration configuration) {
this.configuration = configuration;
}
@Override
// SelfDefaultSqlSessionFactory.openSession
public SelfSqlSession openSession() {
// 获取执行器, executor
SelfExecutor executor = createExecutor();
return new SelfDefaultSqlSession(configuration, executor);
}
private SelfExecutor createExecutor() {
SelfExecutor executor = new SelfSimpleExecutor();
executor = new SelfCachingExecutor(executor);
return executor;
}
}
* 初始化DefaultSqlSession
package com.gupao.self.sqlsession;
import com.gupao.self.config.SelfConfiguration;
import com.gupao.self.executor.SelfExecutor;
import java.lang.reflect.Method;
/**
* 默认的SqlSession
* @author pj_zhang
* @create 2019-03-31 11:04
**/
public class SelfDefaultSqlSession implements SelfSqlSession {
private SelfConfiguration configuration;
private SelfExecutor executor;
public SelfDefaultSqlSession(SelfConfiguration configuration, SelfExecutor executor) {
this.configuration = configuration;
this.executor = executor;
}
}
6,获取执行Mapper
* 客户端触发
// 获取mapper
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
* 转发SqlSession获取Mapper
@Override
// SelfDefaultSqlSession.getMapper
public <T> T getMapper(Class<?> clazz) {
return configuration.getMapper(clazz, this);
}
* 转发Configuration获取Mapper
// 获取mapper
// SelfConfiguration.getMapper
public <T> T getMapper(Class<?> clazz, SelfSqlSession sqlSession) {
return selfMapperRegister.getMapper(clazz, sqlSession);
}
* 转发SelfMapperRegister获取Mapper
// 获取mapper, 通过
public <T> T getMapper(Class<?> clazz, SelfSqlSession sqlSession) {
SelfMapperProxyFactory selfMapperProxyFactory = knowsMapper.get(clazz);
if (null == selfMapperProxyFactory) {
throw new RuntimeException("the execute mapper is not exists");
}
return (T) selfMapperProxyFactory.newInstace(sqlSession);
}
* 提交SelfMapperProxyFactory最终初始化为代理对象,代理对象执行类为SelfMapperProxy
package com.gupao.self.mapper;
import com.gupao.self.sqlsession.SelfSqlSession;
import java.lang.reflect.Proxy;
/**
* @author pj_zhang
* @create 2019-03-31 11:12
**/
public class SelfMapperProxyFactory<T> {
private Class<?> clazz;
public SelfMapperProxyFactory(Class<?> clazz) {
this.clazz = clazz;
}
public <T> T newInstace(SelfSqlSession sqlSession) {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] {clazz}, new SelfMapperProxy(sqlSession));
}
}
7,执行Statement
* 客户端触发
// 执行Statement
List<UserVO> lstData = mapper.selectData();
* 转发代理对象执行类进行执行
package com.gupao.self.mapper;
import com.gupao.self.sqlsession.SelfSqlSession;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author pj_zhang
* @create 2019-03-31 11:21
**/
public class SelfMapperProxy implements InvocationHandler {
private SelfSqlSession sqlSession;
public SelfMapperProxy(SelfSqlSession sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 基层自Object类的方法执行
if (Object.class.equals(method.getDeclaringClass().getClass())) {
return method.invoke(this, args);
}
SelfMapperMethod mapperMethod = createMapperMethod(method);
return mapperMethod.execute(sqlSession, method);
}
private SelfMapperMethod createMapperMethod(Method method) {
return new SelfMapperMethod(method);
}
}
* 转发MapperMethod,进行执行Statement类型划分
package com.gupao.self.mapper;
import com.gupao.self.sqlsession.SelfSqlSession;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Method;
import java.util.List;
/**
* 自定义MapperMethod, 根据查询方式选择不同的策略
* @author pj_zhang
* @create 2019-03-31 12:00
**/
public class SelfMapperMethod {
private Method method;
public SelfMapperMethod(Method method) {
this.method = method;
}
public Object execute(SelfSqlSession sqlSession, Method method) {
// 获取方法名称
String methodName = this.method.getName();
// 区分执行方式, 简易区分
// 数据查询处理, 源码内部根据Statement标签进行了处理
if (StringUtils.isNotEmpty(methodName) && methodName.startsWith("select")) {
Class<?> returnClazz = this.method.getReturnType();
// 返回List集合
if (List.class.getName().equals(returnClazz.getName())) {
// 调用SqlSession查询
return sqlSession.selectList(method);
}
}
return null;
}
}
* 调用SqlSession的select执行语句执行
// SelfDefaultSqlSession.selectList
public Object selectList(Method method) {
// 通过Executor执行器获取结果集
return executor.execute(method);
}
* 调用CachingExecutor,先从缓存中获取数据,获取不到,再从数据库获取
package com.gupao.self.executor;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 缓存执行器
* @author pj_zhang
* @create 2019-03-31 11:36
**/
public class SelfCachingExecutor implements SelfExecutor {
private Map<String, List> cacheMap = new ConcurrentHashMap<>();
private SelfExecutor delegete;
public SelfCachingExecutor(SelfExecutor executor) {
this.delegete = executor;
}
@Override
public <T> List<T> execute(Method method) {
// 拼接缓存key值, 作为SqlSesion级别缓存
String cacheKey = method.getDeclaringClass().getName() + "." + method.getName();
if (cacheMap.containsKey(cacheKey)) {
return cacheMap.get(cacheKey);
}
List<T> lstData = delegete.execute(method);
// 添加结果集到缓存中
cacheMap.put(cacheKey, lstData);
return lstData;
}
}
* 调用SimpleExecutor,从数据库中获取结果集,并完成ORM映射,返回结果!
package com.gupao.self.executor;
import com.gupao.self.mapper.SelfMapperRegister;
import com.gupao.self.pojo.UserVO;
import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* 标准执行器
* @author pj_zhang
* @create 2019-03-31 11:36
**/
public class SelfSimpleExecutor implements SelfExecutor {
@Override
public <T> List<T> execute(Method method) {
List<UserVO> lstData = new ArrayList<>();
try {
// 获取数据库连接
Connection connection = getConnection();
// 连接数据库查询数据
if (method.getDeclaringClass().getName().equals(SelfMapperRegister.SelfMapperMap.NAME_SPACE)) {
String sql = SelfMapperRegister.SelfMapperMap.statement2Sql.get(method.getName());
PreparedStatement statement = connection.prepareStatement(sql);
ResultSet resultSet = statement.executeQuery();
// 进行ORM映射
while (resultSet.next()) {
UserVO userVO = new UserVO();
// 数据库元数据
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
// 映射到VO的属性名
String attrName = metaData.getColumnLabel(i);
// 数据类型
String className = metaData.getColumnClassName(i);
// 获取数据值
Object value = findValue(attrName, className, resultSet);
// 使用BeanUtils填充
BeanUtils.setProperty(userVO, attrName, value);
}
lstData.add(userVO);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return (List<T>) lstData;
}
private Object findValue(String attrName, String className, ResultSet resultSet) {
// 此处需要根据className, 对每一种情况进行识别,
if (String.class.getName().equals(className)) {
try {
return resultSet.getString(attrName);
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
public Connection getConnection() {
Connection connection = null;
try {
String URL="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8";
String USER="root";
String PASSWORD="123456";
//1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
//2.获得数据库链接
connection = DriverManager.getConnection(URL, USER, PASSWORD);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
}
四,结果集
五,代码链接
https://github.com/zpj0427/my_test/tree/master/com-gupao-mybatis