前言

很久没有更新mybatis的源码解析了,因为最近在将自己所理解的mybatis思想转为实践。 在学习mybatis的源码过程中,根据mybatis的思想自己构建了一个ORM框架 。整个代码都是自己手动构造,没有一句代码是Copy,肯定不如谷歌大神那样的代码,但已基本实现了SQL语句的实现和对象关系映射功能。若对源码感兴趣,可加入我一起写这个项目。后文会附带地址,若觉得不错,希望手动star下哦!

项目地址:https://github.com/xbcrh/simple-ibatis

框架介绍

simple-batis是自己编写的一个简单ORM框架。在学习mybatis源码时,有感而发。耗时3周左右,基本满足了一些常用的SQL操作本项目所涉及的代码都是个人所写,没有一句copy,肯定不是很完善,大家理解下,后续有时间会一直更新。如果你对源码感兴趣,也可以加入一起,将自己的理解转为代码真的会加深印象。

框架代码简单梳理

注释 com.simple.ibatis.annotation

@Dao
标注在mapper类上。标志着该类是一个mapper类,在解析时会进行解析

@Dao
public interface App1 {
}

@Select

标注在mapper类中的方法上。标志着该方法是一个Select方法,并在Select方法内部写具体的sql语句。对于有参数注入的情况,参数使用{}进行代替

@Select("SELECT name from sys_user where name = {user.name} and id = {id}")
List<String> test1(User user, int id);

@Param

标注在mapper类中的方法参数上。对参数名进行一次重命名。若不使用此注释,会默认按照参数名当做注入的元素

@Select("SELECT name from sys_user where id = {userId}")
List<String> test2(@Param("userId") int id);

@Update

标注在mapper类中的方法上。标志着该方法是一个Update方法

@Update("update sys_user set name = {user.name} where id = {user.id}")
void update3(User user);

@Insert

标注在mapper类中的方法上。标注着该方法是一个Insert方法

@Insert("insert into sys_user(id,name) values ({user.id},{user.name})")
int insert4(@Param("user") User user);

@Delete

标注在mapper类中的方法上。标注着该方法是一个Delete方法

@Delete("delete from sys_user where id = {user.id}")
int delete5(@Param("user") User user);

数据库注册 com.simple.ibatis.driver

DriverRegister 提供数据库注册功能。未避免重复注册,内部使用了一个缓存

数据源 com.simple.ibatis.datasource

NormalDataSource 普通数据源,没有池化的功能,提供获取数据库连接的功能
PoolDataSource 池化数据源,存放着活跃连接列表和空闲连接列表。并对获取连接和释放连接做了一系列操作
PoolConnection 连接的包装类,除了存放真实连接外,还存放此连接被获取时间,用于判断连接是否超时

核心类 com.simple.ibatis.core

Config 全局核心类,存放数据源,mapper包地址,mapper类解析文件
MapperCore mapper类解析文件
SqlSource 具体的sql语句封装

代理类 com.simple.ibatis.mapping

MapperProxy mapper接口代理类。使用动态代理技术

执行器类 com.simple.ibatis.execute

Executor 执行器接口
SimpleExecutor 具体执行器,执行具体的sql方法。生成结果
ExecutorFactory 生成Executor的工厂类

反射类 com.simple.ibatis.reflect

ClassWrapper 类加强器,封装了Object的get和set方法。
ObjectWrapper 对象包装类。调用ObjectWrapper.setVal和getVal就可以设置和获得属性。不需要显示的调用对象的getxxx和setxxx方法。
ObjectWrapperFactory 对象包装类生成器

处理器类 com.simple.ibatis.statement

PreparedStatementHandle PreparedStatement生成器。将java属性转为jdbc属性并注入。
ResultSetHandle 对查询结构ResultSet进行解析,转换为Java类型

工具类 com.simple.ibatis.util

PackageUti 解析包的工具类
TypeUtil 类型判断的工具类

具体代码实践

1.  代码运行默认在java8上,因为用到了参数反射,所以在idea中记得开启parameters;

File->Settings->Build,Execution,Deployment->Compiler->Java Compiler
在 Additional command line parameters: 后面填上 -parameters

2. 构建pojo文件(记得在数据库也建立一张sys_user表)

public class User {
private int id; private String name; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

2. 构建mapper文件

在mapper文件上加@Dao注解,并为每个方法编写Sql语句,如下所示。目前仅支持注解方式配置SQL,后续会继续完善使其支持.xml文件。

@Dao
public interface App1 { @Select("SELECT * from sys_user")
List<User> select2(); @Select("SELECT name from sys_user where name = {user.name} and id = {id}")
List<String> select3(User user, @Param("id") int id); @Update("update sys_user set name = {user.name} where id = {user.id}")
void update4(User user); @Insert("insert into sys_user(id,name) values ({user.id},{user.name}) ")
int insert5(@Param("user") User user);
}

3. 编写测试类

public class ExecutorTest {

    @Test
public void shouldConnect(){
/**构建数据源,使用时下面代码可设置为全局变量,只加载一次*/
PoolDataSource poolDataSource = new PoolDataSource("com.mysql.jdbc.Driver","jdbc:mysql://101.132.150.75:3306/our-auth","root","root");
ExecutorFactory executorFactory = new ExecutorFactory("com/simple/ibatis/mapper",poolDataSource); /**拿到具体的mapper代理类*/
SimpleExecutor executor = executorFactory.getExecutor();
App1 app1 = executor.getMapper(App1.class); /**构建查询条件*/
User user = new User();
user.setName("xiabing");
user.setId(1); /**调用插入方法*/
int count = app1.insert5(user); /**调用更新方法*/
user.setName("root");
app1.update4(user); /**查询用户名,返回字符*/
List<String> users = app1. select3(user,3);
System.out.println(users.get(0)); /**查询用户,返回对象*/
List<User> userLists = app1.select2();
System.out.println(userLists.get(0).getName()); }
}

最终结果

框架待完善

1.  目前该框架仅支持注解注入SQL语句,不支持XML注入SQL语句

2. 目前对象属性不支持集合类,对象中也不支持嵌套非基本数据类型

3. 框架中没有加入缓存

4. 解析mapper文件仅支持一个包下的mapper文件

结语

正如自己所说,将自己思路变为实践。该框架代码不完善地方很多,但在写的过程中,对mybatis的原理也熟悉了。此框架是我学习的路上的产物。希望小伙伴可以支持下,对源码感兴趣的或想学习mybatis源码的伙伴可以评论下,和我一起写好这个框架,一起开源(学习路上一起加油)

手写mybatis框架的更多相关文章

  1. 要想精通Mybatis?从手写Mybatis框架开始吧!

    1.Mybatis组成 动态SQL Config配置 Mapper配置 2.核心源码分析 Configuration源码解析 SqlSessionFactory源码解析 SqlSession源码解析 ...

  2. 手写mybatis框架笔记

    MyBatis 手写MyBatis流程 架构流程图 封装数据 封装到Configuration中 1.封装全局配置文件,包含数据库连接信息和mappers信息 2.封装*mapper.xml映射文件 ...

  3. 手写mybatis框架-增加缓存&事务功能

    前言 在学习mybatis源码之余,自己完成了一个简单的ORM框架.已完成基本SQL的执行和对象关系映射.本周在此基础上,又加入了缓存和事务功能.所有代码都没有copy,如果也对此感兴趣,请赏个Sta ...

  4. 手写MyBatis ORM框架实践

    一.实现手写Mybatis三个难点 1.接口既然不能被实例化?那么我们是怎么实现能够调用的? 2.参数如何和sql绑定 3.返回结果 下面是Mybatis接口 二.Demo实现 1.创建Maven工程 ...

  5. 手写Spring框架,加深对Spring工作机制的理解!

    在我们的日常工作中,经常会用到Spring.Spring Boot.Spring Cloud.Struts.Mybatis.Hibernate等开源框架,有了这些框架的诞生,平时的开发工作量也是变得越 ...

  6. 带码农《手写Mybatis》进度3:实现映射器的注册和使用

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  7. Spring 08: AOP面向切面编程 + 手写AOP框架

    核心解读 AOP:Aspect Oriented Programming,面向切面编程 核心1:将公共的,通用的,重复的代码单独开发,在需要时反织回去 核心2:面向接口编程,即设置接口类型的变量,传入 ...

  8. 手写 jQuery 框架

    1.测试页面; <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  9. 纯手写Myatis框架

    1.接口层-和数据库交互的方式 MyBatis和数据库的交互有两种方式: 使用传统的MyBatis提供的API: 使用Mapper接口: 2.使用Mapper接口 MyBatis 将配置文件中的每一个 ...

随机推荐

  1. 7月15日考试 题解(链表+状压DP+思维题)

    前言:蒟蒻太弱了,全打的暴力QAQ. --------------------- T1 小Z的求和 题目大意:求$\sum\limits_{i=1}^n \sum\limits_{j=i}^n kth ...

  2. Weblogic 连接 RMI 服务报错 Connection refused

    WebLogic 连接 RMI 服务报错 Connection refused 访问 WebLogic RMI 服务报错,连接被拒绝,连接超时. 奇怪的是,报错的 host 根本不是我要访问的. 报错 ...

  3. C#LeetCode刷题之#231-2的幂(Power of Two)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3858 访问. 给定一个整数,编写一个函数来判断它是否是 2 的幂 ...

  4. C#算法设计排序篇之04-选择排序(附带动画演示程序)

    选择排序(Selection Sort) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/681 访问. 选择排序是一种简 ...

  5. C#LeetCode刷题之#237-删除链表中的节点(Delete Node in a Linked List)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3832 访问. 请编写一个函数,使其可以删除某个链表中给定的(非末 ...

  6. Homekit_Dohome_月球灯

    此款月球灯可以使用Homekit或者Dohome App进行有效的智能控制,支持多种色彩和亮度调节,功能强大,有兴趣的可以去以下链接看看: https://item.taobao.com/item.h ...

  7. Qt 信号发射部分 undefined reference to错误

    在使用信号与槽很容易发生 undefined reference to 发射信号  ①继承QObject ②添加Q_OBJECT ③执行qmake ④构建 然后就可以运行啦!但是不知道是为什么,悄咪咪 ...

  8. Es6扩展运算符--三点运算符(...)--展开语法(Spread syntax)

    0.看文档呀 关于拓展运算符更详细的解释见 > MDN展开语法 关于剩余参数更详细的解释见 >MDN剩余参数 关于解构赋值更详细的解释见 >MDN解构赋值 直接看上面的文档更好 1. ...

  9. 设计模式:建造者模式及在jdk中的体现,建造者模式和工厂模式区别

    0.背景 建造模式(Builder模式) 假如有一个需求:盖房子,盖房子过程是一致的:打桩.砌墙.封顶.但是房子是各式各样的,最后盖出来的房子可能是高楼或别墅. 根据直接的思路,不用设计模式思想,我们 ...

  10. Mybatis-03-日志

    日志 1 日志工厂 如果一个数据库操作,出现了异常,需要排错,此时需要日志. 曾经:sout debug 现在:日志工厂 logImpl SLF4J/log4j(掌握)/log4j2 设置中可以设定日 ...