很久没有更新mybatis的源码解析了,因为最近在将自己所理解的mybatis思想转为实践。 在学习mybatis的源码过程中,根据mybatis的思想自己构建了一个ORM框架 。整个代码都是自己手动构造,没有一句代码是Copy,肯定不如谷歌大神那样的代码,但已基本实现了SQL语句的实现和对象关系映射功能。若对源码感兴趣,可加入我一起写这个项目。后文会附带地址,若觉得不错,希望手动star下哦!
项目地址:simple-ibatis
simple-batis是自己编写的一个简单ORM框架。在学习mybatis源码时,有感而发。耗时3周左右,基本满足了一些常用的Sql操作本项目所涉及的代码都是个人所写,没有一句copy,肯定不是很完善,大家理解下,后续有时间会一直更新。如果你对源码感兴趣,也可以加入一起,将自己的理解转为代码真的会加深印象。
代码运行默认在java8上,因为用到了参数反射,所以在idea中记得开启parameters;
开启步骤如下
1.File->Settings->Build,Execution,Deployment->Compiler->Java Compiler
2.在 Additional command line parameters: 后面填上 -parameters
@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 test1(User user, int id);
@Param
标注在mapper类中的方法参数上。对参数名进行一次重命名。若不使用此注释,会默认按照参数名当做注入的元素。
@Select("SELECT name from sys_user where id = {userId}")
List 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);
DriverRegister 提供数据库注册功能。未避免重复注册,内部使用了一个缓存。
NormalDataSource 普通数据源,没有池化的功能,提供获取数据库连接的功能。
PoolDataSource 池化数据源,存放着活跃连接列表和空闲连接列表。并对获取连接和释放连接做了一系列操作。
PoolConnection 连接的包装类,除了存放真实连接外,还存放此连接被获取时间,用于判断连接是否超时。
Config 全局核心类,存放数据源,mapper包地址,mapper类解析文件
MapperCore mapper类解析文件
SqlSource 具体的sql语句封装
MapperProxy mapper接口代理类。使用动态代理技术
Executor 执行器接口
SimpleExecutor 具体执行器,执行具体的sql方法。生成结果
ExecutorFactory 生成Executor的工厂类
ClassWrapper 类加强器,封装了Object的get和set方法。
ObjectWrapper 对象包装类。调用ObjectWrapper.setVal和getVal就可以设置和获得属性。不需要显示的调用对象的getxxx和setxxx方法。
ObjectWrapperFactory 对象包装类生成器
PreparedStatementHandle PreparedStatement生成器。将java属性转为jdbc属性并注入。
ResultSetHandle 对查询结构ResultSet进行解析,转换为Java类型
PackageUti 解析包的工具类
TypeUtil 类型判断的工具类
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;
}
}
package com.simple.ibatis.mapper;
@Dao
public interface App1 {
@Select("SELECT * from sys_user")
List select2();
@Select("SELECT name from sys_user where name = {user.name} and id = {id}")
List 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);
}
PoolDataSource poolDataSource = new PoolDataSource("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/auth","root","root");
/**输入mapper文件所在包及数据源*/
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 users = app1. select3(user,3);
System.out.println(users.get(0));
/**查询用户,返回对象*/
List userLists = app1.select2();
System.out.println(userLists.get(0).getName());
正如自己所说,将自己思路变为实践。该框架代码不完善地方很多,但在写的过程中,对mybatis的原理也熟悉了。此框架是我学习的路上的产物。希望小伙伴可以支持下,对源码感兴趣的或想学习mybatis源码的伙伴可以评论下,和我一起写好这个框架,一起开源(学习路上一起加油)