手寫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源碼的夥伴能夠評論下,和我一塊兒寫好這個框架,一塊兒開源(學習路上一塊兒加油)

相關文章
相關標籤/搜索