MyBatis源码解析(七):手写实现简易MyBatis框架

一,执行流程图

二,执行步骤分析

    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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值