手写mybatis框架

前言

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

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

框架介绍

simple-batis是本身编写的一个简单ORM框架。在学习mybatis源码时,有感而发。耗时3周左右,基本知足了一些经常使用的SQL操做本项目所涉及的代码都是我的所写,没有一句copy,确定不是很完善,你们理解下,后续有时间会一直更新。若是你对源码感兴趣,也能够加入一块儿,将本身的理解转为代码真的会加深印象。git

框架代码简单梳理

注释 com.simple.ibatis.annotation

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

@Dao
public interface App1 {
}

@Selectsql

标注在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类中的方法参数上。对参数名进行一次重命名。若不使用此注释,会默认按照参数名当作注入的元素mybatis

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

@Updateapp

标注在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 类型判断的工具类

缓存类 com.simple.ibatis.cache

Cache 缓存接口类

SimpleCache 简单缓存类

 

具体代码实践

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");
Config config = new Config("com/simple/ibatis/mapper",poolDataSource);
/**拿到具体的mapper代理类*/ SimpleExecutor executor = config.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源码的伙伴能够评论下,和我一块儿写好这个框架,一块儿开源(学习路上一块儿加油)

相关文章
相关标签/搜索