`

手写MyBatis,纯手工打造开源框架(第三篇:运筹帷幄)

阅读更多

说明

MyBatis版本:3.5.1

 

相关历史文章(阅读本文之前,您可能需要先看下之前的系列

Spring Boot MyBatis最全教程:你值得拥有
MyBatis能脱离Spring吗一图纵览MyBatis的工作原理
从源码看MyBatis,竟如此简单MyBatis的Mapper是什么`垃圾` 

手写MyBatis,纯手工打造开源框架(第一篇:风云再起)

手写MyBatis,纯手工打造开源框架(第二篇:君临天下) 

 

前言

       通过上面我们已经可以构建了SqlSessionFactory,接下来的话就是要怎么获取一个SqlSession。

 

一、分析

       对于SqlSession的构建的话,需要有一个属性Configuration,这个属性在上面的SqlSessionFactory已经有了;另外对于SqlSession的真正的Sql执行是交给了Executor,Executor是真正和数据库进行交互了,所以需要将数据库配置信息传给Executor。

 

二、编码

2.1 Executor

       构造SqlSession需要有Executor,我们先创建一个Executor接口:

package com.kfit.mybatis.session;

import java.util.List;

import com.kfit.mybatis.config.MapperStatement;

public interface Executor {
     <E> List<E> query(MapperStatement ms, Object parameter);
}
 

       我们实现一个最基本的SimpleExecutor:

package com.kfit.mybatis.session.impl;

import java.util.List;

import com.kfit.mybatis.config.JdbcProperties;
import com.kfit.mybatis.config.MapperStatement;
import com.kfit.mybatis.session.Executor;

public class SimpleExecutor implements Executor {
    private JdbcProperties jdbcProperties;

    public SimpleExecutor(JdbcProperties jdbcProperties) {
        this.jdbcProperties = jdbcProperties;
    }

    public <E> List<E> query(MapperStatement ms, Object parameter) {
        //具体的方法待实现

        return null;
    }

}
 

说明:

(1)这里我们实现了最基本的Simple,在MyBatis有3情况需要处理,我们实现最简单的方式。

(2)这里我们接收了jdbcproperties为了之后直接进行数据库的连接操作,在mybatis数据库的连接关闭,提交,回滚是有一个事务类Transaction。

 

2.2 SqlSessionFactory

       在SqlSessionFactory中添加一个获取SqlSession的方法:

public interface SqlSessionFactory {
    public Configuration getConfiguration();
    public SqlSession openSession();
}
 

 

       在DefaultSqlSessionFactory实现openSession()方法:

    public SqlSession openSession() {
        Executor executor = new SimpleExecutor(configuration.getJdbcProperties());
        SqlSession sqlSession = new DefaultSqlSession(configuration, executor);
        return sqlSession;
    }
 

 

2.3 SimpleExecutor数据库操作

       我们这个对数据库操作的核心代码:

 

package com.kfit.mybatis.session.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.kfit.mybatis.config.JdbcProperties;
import com.kfit.mybatis.config.MapperStatement;
import com.kfit.mybatis.session.Executor;

public class SimpleExecutor implements Executor {
    private JdbcProperties jdbcProperties;

    public SimpleExecutor(JdbcProperties jdbcProperties) {
        this.jdbcProperties = jdbcProperties;
    }

    public <E> List<E> query(MapperStatement ms, Object parameter) {
        List<E> ret = new ArrayList<E>();
        // 具体的方法待实现
        try {
            // 加载驱动
            Class.forName(jdbcProperties.getDriver());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Connection connection = null;

        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            // 获取连接
            connection = DriverManager.getConnection(jdbcProperties.getUrl(), jdbcProperties.getUsername(),
                    jdbcProperties.getPassword());
            // 预编译sql语句
            preparedStatement = connection.prepareStatement(ms.getSql());
            // 处理sql语句中的占位符
            parameterize(preparedStatement, parameter);
            // 执行sql语句
            resultSet = preparedStatement.executeQuery();
            // 处理结果
            handlerResultSet(resultSet, ret, ms.getResultType());
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return ret;
    }

    private void parameterize(PreparedStatement preparedStatement, Object parameter) throws SQLException {
        if (parameter instanceof String) {
            preparedStatement.setString(1, (String) parameter);
        } else if (parameter instanceof Long) {
            preparedStatement.setLong(1, (Long) parameter);
        } else if (parameter instanceof Integer) {
            preparedStatement.setInt(1, (Integer) parameter);
        }
    }

    private <E> void handlerResultSet(ResultSet resultSet, List<E> ret, String className) {
        Class<E> clazz = null;
        try {
            clazz = (Class<E>) Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            while (resultSet.next()) {
                // 通过反射实例化对象
                Object entity = clazz.newInstance();
                // 使用反射工具将resultSet中的数据填充到entity中
                // id,name,sex,age
                // 获取实体类的所有属性,返回Field数组
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    String fname = field.getName();
                    Type type = field.getGenericType();
                    if (type.toString().equals("class java.lang.String")) {
                        String column = resultSet.getString(fname);
                        field.set(entity, column);
                    }else if (type.toString().equals("long")) {
                        Long column = resultSet.getLong(fname);
                        field.set(entity, column);
                    }
                }
                ret.add((E) entity);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

}
 

说明:

(1)在MyBatis中这个代码是分好几个类进行处理的,这里为了讲解方便,统一放在一个类中。

(2)数据库的连接操作:这里使用jdbc连接数据库获取到connection进行操作。

(3)使用泛型处理返回的结果(handlerResultSet)。

 

2.4 SqlSession的方法

       到这里,我们就可以编写SqlSession的方法了,这里定义两个方法SelectOne和SelectList();

 

public interface SqlSession {
     <T> T selectOne(String statement, Object parameter);
     <E> List<E> selectList(String statement);
<E> List<E> selectList(String statement, Object parameter);
}
 

       对应的DefaultSqlSession:

 

package com.kfit.mybatis.session.impl;


import java.util.List;

import com.kfit.mybatis.config.Configuration;
import com.kfit.mybatis.session.Executor;
import com.kfit.mybatis.session.SqlSession;

public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;
    private Executor executor;
    public DefaultSqlSession(Configuration configuration,Executor executor) {
        this.configuration= configuration;
        this.executor = executor;
    }


    public <E> List<E> selectList(String statement) {
        return executor.query(configuration.getMapperStatement(statement),null);
    }

public <E> List<E> selectList(String statement,Object parameter) {
        return executor.query(configuration.getMapperStatement(statement), parameter);
    }


    public <T> T selectOne(String statement,Object parameter) {
        List<T> list = executor.query(configuration.getMapperStatement(statement),parameter);
        if(list.size()>0) {
            return list.get(0);
        }
        return null;
    }
}

 

 

说明:DefaultSqlSession的具体处理交给了Executor,所以这里的具体的实现就比较简单了。

2.5 测试下

       在main方法来进行测试一下吧:

 

 
   public static void main(String[] args) {
        String resource = "mybatis-config.xml";
        InputStream inputStream = App.class.getClassLoader().getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        System.out.println(sqlSessionFactory);
        System.out.println(sqlSessionFactory.getConfiguration().getJdbcProperties().getUrl());

        SqlSession sqlSession = sqlSessionFactory.openSession();


        Demo demo = null;
        List<Demo> demos = null;

        //使用sqlSession直接查询
        demo = sqlSession.selectOne("com.kfit.mybatis.demo.mapper.DemoMapper.getById",1L);
        System.out.println(demo);
        demos = sqlSession.selectList("com.kfit.mybatis.demo.mapper.DemoMapper.getAll");
        System.out.println(demos);

    }
 

       这个方法和之前写mybatis的使用方式上是一模一样的,运行看下效果吧:

Demo[id=1, name=张三1]

[Demo [id=1, name=张三1], Demo [id=9, name=张三], Demo [id=10, name=张三], Demo [id=11, name=张三], Demo [id=12, name=张三], Demo [id=13, name=张三]]

 

 

       看到如此帅气的结果,这是爽歪歪,厉害了我的哥。本篇就先介绍到这里,下一篇我们将会介绍无敌的Mapper实现。

我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。

à悟空学院:https://t.cn/Rg3fKJD

学院中有Spring Boot相关的课程!点击「阅读原文」进行查看!

SpringBoot视频:http://t.cn/A6ZagYTi

Spring Cloud视频:http://t.cn/A6ZagxSR

SpringBoot Shiro视频:http://t.cn/A6Zag7IV

SpringBoot交流平台:https://t.cn/R3QDhU0

SpringData和JPA视频:http://t.cn/A6Zad1OH

SpringSecurity5.0视频:http://t.cn/A6ZadMBe

Sharding-JDBC分库分表实战http://t.cn/A6ZarrqS

分布式事务解决方案「手写代码」:http://t.cn/A6ZaBnIr

分享到:
评论

相关推荐

    手写mybatis框架源码由浅入深

    手写mybatis框架源码 不借助其他任何框架,从最底层开始着手,用最简单的代码,将mybatis的底层框架,手写出来,让你对mybatis有一个更加深刻和直观的理解 详见:...

    手写mybatis核心流程代码demo

    手写mybatis核心流程代码demo手写mybatis核心流程代码demo手写mybatis核心流程代码demo手写mybatis核心流程代码demo手写mybatis核心流程代码demo手写mybatis核心流程代码demo手写mybatis核心流程代码demo手写mybatis...

    开源框架面试题系列:Spring+SpringMVC+MyBatis

    在IT行业中,开源框架是构建复杂应用程序的基础,而Spring、SpringMVC和MyBatis作为Java领域的三大核心框架,它们的熟练掌握对于开发者来说至关重要。本系列主要关注这些框架在面试中的常见问题,旨在帮助求职者提升...

    手写mybatis

    本篇文章将深入探讨如何手写Mybatis的核心功能,包括基础的数据库访问、XML映射文件解析以及动态代理机制。 一、数据库访问基础 手写Mybatis的第一步是实现基于JDBC的数据库访问。这通常涉及以下步骤: 1. 数据库...

    开源框架面试题系列:Spring+SpringMVC+MyBatis.rar

    在IT行业中,Java技术栈是企业级应用开发的主流选择,Spring、SpringMVC和MyBatis这三大开源框架更是核心组件。对于求职者来说,掌握这三个框架的深入理解和使用技巧,是通过技术面试的关键。以下是对这三者进行详细...

    开源框架面试题系列:Spring+SpringMVC+MyBatis.zip

    在IT行业中,Spring、SpringMVC和MyBatis是三个非常重要的开源框架,它们在企业级Java应用开发中占据了核心地位。本压缩包文件提供的面试题系列,旨在帮助求职者和开发者深入理解这三个框架的核心概念、工作原理以及...

    阿里巴巴P7架构师纯手工打造MyBatis源码——1小时解密底层源码.txt

    本篇文章将基于阿里巴巴P7架构师纯手工打造的MyBatis源码解析资料,深入探讨MyBatis的核心原理及其内部实现机制。本文旨在帮助读者理解MyBatis的工作原理,并为日后进行更深层次的技术研究提供一定的理论基础。 ###...

    Mybatis注解手写源码篇

    Mybatis是中国著名的开源持久层框架,它提供了灵活的SQL映射功能和基于Java的映射文件,使得开发者能够方便地将数据库操作与业务逻辑相分离。在本项目中,我们将探讨如何手写模拟Mybatis的注解实现,深入了解其参数...

    手写mybatis实现查询所有操作

    MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。在本文中,我们将深入探讨如何手写MyBatis实现查询所有操作,以加深对其工作原理的理解。 首先,我们需要理解MyBatis的核心组件。MyBatis...

    手写简易mybatis

    【标题】"手写简易mybatis"涉及到的知识点主要涵盖了MyBatis框架的核心概念和实现原理,这包括了配置文件解析、SQL会话管理、Mapper注解以及动态代理技术的应用。下面将对这些主题进行详细阐述。 首先,**配置文件...

    开发工具 框架JAR mybatis-3.4.2

    开发工具 框架JAR mybatis-3.4.2开发工具 框架JAR mybatis-3.4.2开发工具 框架JAR mybatis-3.4.2开发工具 框架JAR mybatis-3.4.2开发工具 框架JAR mybatis-3.4.2开发工具 框架JAR mybatis-3.4.2开发工具 框架JAR ...

    深入剖析:从基础到进阶,手写MyBatis框架源码详解

    手写mybatis框架源码 不借助其他任何框架,从最底层开始着手,用最简单的代码,将mybatis的底层框架,手写出来,让你对mybatis有一个更加深刻和直观的理解 详见:...

    手写简易版ORM框架(仿mybatis)

    ORM,全称Object-Relational ...学习并实践手写ORM框架,不仅有助于理解数据库操作的本质,还能加深对MyBatis等成熟ORM框架的理解。通过这种方式,开发者可以更好地掌握数据持久化的原理,提升在实际项目中的应用能力。

    手写mybatis实现,剖析mybatis底层原理

    手写mybatis实现,剖析mybatis底层原理

    采用SpringBoot2.0、MyBatis-Plus、Shiro框架,开发的一套权限系统.zip

    采用SpringBoot2.0、MyBatis-Plus、Shiro框架,开发的一套权限系统 采用SpringBoot2.0、MyBatis-Plus、Shiro框架,开发的一套权限系统 采用SpringBoot2.0、MyBatis-Plus、Shiro框架,开发的一套权限系统 采用...

    手写mybatis单表查询实现-cnblog.md

    手写实现mybatis,mybatis处理流程图,mybatis实现需要的几个函数,各个函数的调用。

    仿照 Mybatis 手写 ROM 框架.rar

    【标题】"仿照 Mybatis 手写 ROM 框架"揭示了这个项目的核心目标——构建一个类似于 Mybatis 的自定义数据访问框架。Mybatis 是一个著名的 Java ORM(对象关系映射)框架,它允许开发者用 SQL 语句直接操作数据库,...

    开源框架面试题系列集:Spring+SpringMVC+MyBatis.zip

    在IT行业中,开源框架是开发高效、稳定应用的基石,Spring、SpringMVC和MyBatis作为Java领域的三大核心框架,被广泛应用于企业级开发。本资料集合专注于这些框架的面试题,旨在帮助求职者和开发者更好地理解和掌握...

    mybatis生成工具(纯手写,附带注释)

    MyBatis 是一款著名的持久层框架,它支持定制化 SQL、存储过程以及高级映射。在本项目中,你提供的是一个自编写的 MyBatis 生成工具,它旨在简化数据库与 Java 模型之间的映射工作,提高开发效率。这个工具的特别之...

    fluent-mybatis, mybatis语法增强框架

    `fluent-mybatis` 作为一个活跃的开源项目,有着丰富的文档和社区支持,遇到问题时可以快速获取帮助和解决方案。 在 `fluent-mybatis-master` 压缩包中,包含了项目的源码、示例、文档以及构建脚本等资源,开发者...

Global site tag (gtag.js) - Google Analytics