Skip to content

Nicander93/mini-mybatis

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mini-mybatis

一个用于学习 MyBatis / mybatis-spring 核心机制的迷你多模块项目。

这个仓库不是为了实现完整框架,而是把最关键的主链路拆出来:从 JDBC 和 DAO 层的重复劳动出发,理解 MyBatis 如何把 Mapper 接口调用变成 SQL 执行,再理解 mybatis-spring 如何把 Mapper 代理注册成 Spring Bean。

模块结构

mini-mybatis-parent
├── mini-mybatis          原生 MyBatis 核心机制
└── mini-mybatis-spring   mini 版 org.mybatis:mybatis-spring:3.0.0 适配层

mini-mybatis 负责 SQL 执行主链路:

  • SqlSessionFactory / SqlSession
  • Mapper 接口动态代理
  • @Select / @Insert / @Update / @Delete 注解映射
  • XML mapper 映射
  • #{} 参数绑定到 PreparedStatement
  • ResultSet 按列名映射到 JavaBean

mini-mybatis-spring 负责 Spring 集成主链路:

  • SqlSessionFactoryBean
  • SqlSessionTemplate
  • MapperFactoryBean
  • @MapperScan

架构图

mini-mybatis

flowchart TB;
    subgraph ApplicationLayer;
        Service[业务代码];
        Mapper[Mapper接口];
    end;

    subgraph SessionProxyLayer;
        Factory[MiniSqlSessionFactory];
        Session[SqlSession];
        Proxy[MapperProxy];
    end;

    subgraph MappingLayer;
        Config[Configuration];
        Statement[MappedStatement];
        SqlSource[注解和XML SQL];
    end;

    subgraph SqlExecutionLayer;
        Parser[SqlSourceParser];
        Executor[SimpleExecutor];
        ResultMap[结果映射];
    end;

    subgraph DatabaseLayer;
        JDBC[DataSource和JDBC];
        DB[(Database)];
    end;

    Service --> Mapper;
    Mapper --> Proxy;
    Factory --> Session;
    Session --> Proxy;
    SqlSource --> Config;
    Config --> Statement;
    Proxy --> Statement;
    Proxy --> Session;
    Session --> Executor;
    Statement --> Parser;
    Parser --> Executor;
    Executor --> JDBC;
    JDBC --> DB;
    DB --> JDBC;
    JDBC --> ResultMap;
    ResultMap --> Service;
Loading

一次原生 Mapper 调用可以简化为:

mapper.findById(1L)
  -> MapperProxy
  -> MappedStatement
  -> SqlSourceParser
  -> SimpleExecutor
  -> JDBC
  -> ResultSet 映射

mini-mybatis-spring

flowchart TB;
    subgraph SpringApplicationLayer;
        ConfigClass[Configuration];
        MapperScan[MapperScan];
        UserService[Service];
        MapperBean[UserMapper Bean];
    end;

    subgraph MyBatisSpringAdapterLayer;
        SFB[SqlSessionFactoryBean];
        Template[SqlSessionTemplate];
        Registrar[MapperScannerRegistrar];
        Scanner[SimpleMapperScanner];
        MFB[MapperFactoryBean];
    end;

    subgraph NativeMiniMyBatisLayer;
        NativeFactory[MiniSqlSessionFactory];
        NativeSession[SqlSession];
        NativeProxy[MapperProxy];
        NativeExecutor[Executor和JDBC];
    end;

    ConfigClass --> SFB;
    ConfigClass --> Template;
    MapperScan --> Registrar;
    Registrar --> Scanner;
    Scanner --> MFB;
    SFB --> NativeFactory;
    Template --> NativeFactory;
    MFB --> Template;
    MFB --> MapperBean;
    UserService --> MapperBean;
    MapperBean --> Template;
    Template --> NativeSession;
    NativeSession --> NativeProxy;
    NativeProxy --> NativeExecutor;
Loading

Spring 集成后的核心变化是:

Mapper 接口
  -> @MapperScan 注册 MapperFactoryBean
  -> MapperFactoryBean 暴露 Mapper 代理
  -> SqlSessionTemplate 管理 SqlSession 调用
  -> 复用原生 mini-mybatis 执行链路

运行测试

mvn test

也可以只运行单个模块:

mvn -pl mini-mybatis test
mvn -pl mini-mybatis-spring test

快速示例

原生 mini-mybatis

MiniSqlSessionFactory factory = new MiniSqlSessionFactoryBuilder()
        .dataSource(dataSource)
        .addMapper(UserMapper.class)
        .addXmlMapper("mapper/UserXmlMapper.xml")
        .build();

try (SqlSession session = factory.openSession()) {
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user = mapper.findById(1L);
}

Spring 集成

@Configuration
@MapperScan("com.example.mapper")
class AppConfig {
    @Bean
    SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setMapperInterfaces(new Class<?>[]{UserMapper.class});
        factoryBean.setMapperLocations(new String[]{"mapper/UserMapper.xml"});
        return factoryBean;
    }

    @Bean
    SqlSessionTemplate sqlSessionTemplate(MiniSqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

之后业务代码可以直接从 Spring 容器注入 Mapper:

class UserService {
    private final UserMapper userMapper;

    UserService(UserMapper userMapper) {
        this.userMapper = userMapper;
    }
}

核心源码入口

mini-mybatis

mini-mybatis-spring

学习文档

支持范围

当前已支持:

  • 静态 SQL
  • #{} 占位符
  • 注解 Mapper
  • XML Mapper
  • JDK 动态代理
  • 简单 JavaBean 映射
  • 基础增删改查
  • Spring FactoryBean 集成
  • 简单 @MapperScan

暂不包含:

  • 动态 SQL,如 <if><where><foreach>
  • 一级缓存、二级缓存
  • 插件拦截器
  • TypeHandler 注册表
  • 复杂 ResultMap
  • Spring 事务同步
  • 异常翻译
  • Spring Boot 自动配置

About

一个 mini-mybatis /mini-mybatis-spring 项目,用于帮助学习源码

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages