很久没有更新mybatis的源码解析了,因为最近在将自己所理解的mybatis思想转为实践。 在学习mybatis的源码过程中,根据mybatis的思想自己构建了一个ORM框架 。整个代码都是自己手动构造,没有一句代码是Copy,肯定不如谷歌大神那样的代码,但已基本实现了SQL语句的实现和对象关系映射功能。若对源码感兴趣,可加入我一起写这个项目。后文会附带地址,若觉得不错,希望手动star下哦!
项目地址:https://github.com/xbcrh/simple-ibatis
simple-batis是自己编写的一个简单ORM框架。在学习mybatis源码时,有感而发。耗时3周左右,基本满足了一些常用的SQL操作本项目所涉及的代码都是个人所写,没有一句copy,肯定不是很完善,大家理解下,后续有时间会一直更新。如果你对源码感兴趣,也可以加入一起,将自己的理解转为代码真的会加深印象。
@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);
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 类型判断的工具类
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源码的伙伴可以评论下,和我一起写好这个框架,一起开源(学习路上一起加油)
原文:https://www.cnblogs.com/xiaobingblog/p/13617159.html