# mybatis-max
**Repository Path**: talins/mybatis-max
## Basic Information
- **Project Name**: mybatis-max
- **Description**: 革命性的 ORM 框架
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2024-03-28
- **Last Updated**: 2026-02-28
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# MyBatis-Max
🚀 基于 MyBatis-Plus 的零代码动态 ORM 框架
English |
快速开始 |
核心特性 |
架构设计
---
## 📖 项目简介
**MyBatis-Max** 是一个革命性的 ORM 框架,它彻底消除了编写 Entity 实体类和 Mapper 接口的需要。框架在应用启动时自动读取数据库表结构,使用 Groovy 动态生成所有必要的代码,并通过统一的 Repository 接口提供完整的 CRUD 操作。
### 为什么选择 MyBatis-Max?
| 传统开发方式 | MyBatis-Max |
|-------------|-------------|
| 为每个表创建 Entity 类 | ✅ 运行时自动生成 |
| 为每个表创建 Mapper 接口 | ✅ 运行时自动生成 |
| 编写 XML 或注解 SQL | ✅ 内置通用操作 |
| 表结构变更需修改代码 | ✅ 重启自动适配 |
| 重复的 CRUD 样板代码 | ✅ 一个接口操作所有表 |
## ✨ 核心特性
- **🔄 动态代码生成** - 根据数据库表结构自动生成 Entity 和 Mapper 类
- **📦 零配置启动** - 只需添加依赖并配置数据源即可使用
- **🎯 统一仓库接口** - 单一接口完成所有表的数据操作
- **📄 内置分页支持** - 原生支持分页查询
- **🔐 数据权限控制** - 支持行级和列级权限控制
- **💾 二级缓存** - 集成 J2Cache 实现高性能缓存
- **🔀 多数据源** - 动态数据源切换,自动路由
- **📡 事件系统** - 操作前后事件,便于业务扩展
- **🌐 REST API** - 开箱即用的 RESTful 接口
- **❄️ 雪花 ID** - 分布式唯一 ID 生成
## 🏗️ 架构设计
### 项目结构
```
mybatis-max
├── mybatis-max-api # 核心接口和 POJO 定义
├── mybatis-max-sdk # 核心实现(Repository、缓存、事件)
├── mybatis-max-spring-boot-starter # Spring Boot 自动配置
├── mybatis-max-web # REST API 控制器
└── mybatis-max-test # 测试模块和示例
```
### 核心组件
```
┌─────────────────────────────────────────────────────────────────┐
│ 应用层 │
├─────────────────────────────────────────────────────────────────┤
│ BaseRest (REST API) │ IRepositoryService (业务服务层) │
├─────────────────────────────────────────────────────────────────┤
│ IRepository / DataPermissionRepository │
├─────────────────────────────────────────────────────────────────┤
│ DynamicMapperUtil │ IRepositoryHandler │ CacheUtil │
├─────────────────────────────────────────────────────────────────┤
│ MyBatis-Plus BaseMapper (自动生成) │
├─────────────────────────────────────────────────────────────────┤
│ DataSource (单数据源/动态数据源) │
└─────────────────────────────────────────────────────────────────┘
```
### 运行流程
```
应用启动
│
▼
┌─────────────────────────────────────┐
│ DynamicMapperBeanFactoryPostProcessor│
│ 1. 连接数据库 │
│ 2. 读取所有表的元数据 │
│ 3. 使用 Groovy 动态生成 Entity 类 │
│ 4. 使用 Groovy 动态生成 Mapper 接口 │
│ 5. 注册 Mapper 为 Spring Bean │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ BeanConfiguration │
│ 注册 Repository、Handler 等 Bean │
└─────────────────────────────────────┘
│
▼
应用就绪,可通过 Repository 或 REST API 操作任意表
```
## 🚀 快速开始
### 环境要求
- Java 11+
- Spring Boot 2.6.x
- MySQL 5.7+ / 其他 JDBC 兼容数据库
### Maven 依赖
```xml
cn.talins
mybatis-max-spring-boot-starter
1.0.0-SNAPSHOT
cn.talins
mybatis-max-web
1.0.0-SNAPSHOT
```
### 配置文件
```yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
# 可选:分布式部署时配置雪花算法工作节点 ID
mybatis:
max:
worker-id: 1
```
### 数据库表设计规范
为了充分利用框架功能,建议表包含以下基础字段:
```sql
CREATE TABLE your_table (
id BIGINT(19) PRIMARY KEY COMMENT '主键ID(自动生成雪花ID)',
normal TINYINT(3) DEFAULT 1 COMMENT '逻辑删除标识:1-正常,0-已删除',
version BIGINT(19) COMMENT '乐观锁版本号',
update_time DATETIME COMMENT '最后更新时间',
extra TEXT COMMENT '扩展字段(JSON格式)',
-- 其他业务字段...
);
```
## 📚 使用指南
### 方式一:使用 REST API(零代码)
应用启动后,所有表自动暴露 REST 接口:
```bash
# 插入记录
POST /mybatis-max/insert/user
{
"param": {"name": "张三", "age": 25, "email": "zhangsan@example.com"}
}
# 根据 ID 查询
POST /mybatis-max/selectById/user
{
"param": 1
}
# 条件查询
POST /mybatis-max/selectList/user
{
"param": {
"conditionList": [
{"column": "age", "operator": "GREAT_EQUAL", "paramList": [18]}
],
"orderMap": {"createTime": "DESC"}
}
}
# 分页查询
POST /mybatis-max/selectPage/user
{
"pageNum": 1,
"pageSize": 10,
"param": {
"conditionList": [
{"column": "status", "operator": "EQUAL", "paramList": [1]}
]
}
}
# 根据 ID 更新
POST /mybatis-max/updateById/user
{
"param": {"id": 1, "name": "李四", "age": 26}
}
# 根据 ID 删除
POST /mybatis-max/deleteById/user
{
"param": 1
}
# 批量删除
POST /mybatis-max/deleteBatchIds/user
{
"param": [1, 2, 3]
}
# 判断是否存在
POST /mybatis-max/exists/user
{
"param": {
"conditionList": [
{"column": "email", "operator": "EQUAL", "paramList": ["test@example.com"]}
]
}
}
# 统计数量
POST /mybatis-max/selectCount/user
{
"param": {
"conditionList": [
{"column": "status", "operator": "EQUAL", "paramList": [1]}
]
}
}
```
### 方式二:在代码中使用 Repository
```java
@Service
public class UserService {
@Autowired
private BaseRepository baseRepository;
// 插入
public Long createUser(Map user) {
return baseRepository.insert("user", user);
}
// 根据 ID 查询
public User getUser(Long id) {
return baseRepository.selectById("user", id, User.class);
}
// 条件查询
public List findActiveUsers() {
QueryWrapper wrapper = Wrappers.query(User.class);
wrapper.eq("status", 1)
.orderByDesc("create_time");
return baseRepository.selectList("user", wrapper);
}
// 分页查询
public IPage pageUsers(int pageNum, int pageSize) {
Page page = new Page<>(pageNum, pageSize);
QueryWrapper wrapper = Wrappers.query(User.class);
return baseRepository.selectPage("user", page, wrapper);
}
// 更新
public int updateUser(Map user) {
return baseRepository.updateById("user", user);
}
// 删除
public int deleteUser(Long id) {
return baseRepository.deleteById("user", id);
}
// 根据 Map 条件查询
public List findByCondition(Map condition) {
return baseRepository.selectByMap("user", condition, User.class);
}
}
```
### 方式三:继承服务抽象类
```java
@Service
public class UserService extends AbstractBaseRepositoryService {
public UserService(BaseRepository baseRepository) {
super(baseRepository);
}
@Override
protected String getTableName() {
return "user";
}
// 现在可以直接使用继承的方法,无需指定表名
// insert(), selectById(), updateById(), deleteById() 等
// 自定义业务方法
public User findByUsername(String username) {
return selectOneByMap(Map.of("username", username), User.class);
}
}
```
## 🔧 高级功能
### 查询操作符
| 操作符 | 说明 | 示例 |
|--------|------|------|
| `EQUAL` | 等于 (=) | `{"column": "status", "operator": "EQUAL", "paramList": [1]}` |
| `NOT_EQUAL` | 不等于 (!=) | `{"column": "status", "operator": "NOT_EQUAL", "paramList": [0]}` |
| `LIKE` | 模糊匹配 | `{"column": "name", "operator": "LIKE", "paramList": ["%张%"]}` |
| `NOT_LIKE` | 不匹配 | `{"column": "name", "operator": "NOT_LIKE", "paramList": ["%test%"]}` |
| `IN` | 包含 | `{"column": "id", "operator": "IN", "paramList": [1, 2, 3]}` |
| `NOT_IN` | 不包含 | `{"column": "status", "operator": "NOT_IN", "paramList": [0, -1]}` |
| `BETWEEN` | 范围 | `{"column": "age", "operator": "BETWEEN", "paramList": [18, 30]}` |
| `NOT_BETWEEN` | 范围外 | `{"column": "age", "operator": "NOT_BETWEEN", "paramList": [0, 18]}` |
| `GREAT` | 大于 (>) | `{"column": "age", "operator": "GREAT", "paramList": [18]}` |
| `LESS` | 小于 (<) | `{"column": "age", "operator": "LESS", "paramList": [60]}` |
| `GREAT_EQUAL` | 大于等于 (>=) | `{"column": "age", "operator": "GREAT_EQUAL", "paramList": [18]}` |
| `LESS_EQUAL` | 小于等于 (<=) | `{"column": "age", "operator": "LESS_EQUAL", "paramList": [60]}` |
| `IS_NULL` | 为空 | `{"column": "email", "operator": "IS_NULL", "paramList": []}` |
| `IS_NOT_NULL` | 不为空 | `{"column": "email", "operator": "IS_NOT_NULL", "paramList": []}` |
### 条件连接
多个条件默认使用 `AND` 连接,可通过 `connect` 字段指定 `OR` 连接:
```json
{
"param": {
"conditionList": [
{"column": "status", "operator": "EQUAL", "paramList": [1]},
{"column": "type", "operator": "EQUAL", "paramList": [2], "connect": "OR"}
]
}
}
```
### 多数据源配置
```yaml
spring:
datasource:
master:
url: jdbc:mysql://localhost:3306/master_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
slave:
url: jdbc:mysql://localhost:3306/slave_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
```
框架会自动根据表所在的数据源进行路由,无需手动切换。
### 数据权限控制
实现 `IDataPermissionHandler` 接口添加行级/列级权限:
```java
@Bean
public IDataPermissionHandler dataPermissionHandler() {
return new IDataPermissionHandler() {
@Override
public void addRowPermission(String tableName, QueryWrapper wrapper) {
// 添加租户隔离条件
wrapper.eq("tenant_id", getCurrentTenantId());
// 添加部门数据范围
wrapper.in("dept_id", getCurrentUserDeptIds());
}
@Override
public T addColumnPermission(String tableName, T entity) {
// 敏感字段脱敏
if (entity instanceof User) {
User user = (User) entity;
user.setPhone(maskPhone(user.getPhone()));
user.setIdCard(maskIdCard(user.getIdCard()));
}
return entity;
}
@Override
public List addColumnPermission(String tableName, List list) {
return list.stream()
.map(e -> addColumnPermission(tableName, e))
.collect(Collectors.toList());
}
};
}
```
### 事件监听
监听实体操作事件进行业务扩展:
```java
@Component
public class EntityEventListener {
@EventListener
public void onInsert(EntityInsertEvent event) {
if (event.getIsBefore() == 1) {
// 插入前
log.info("准备插入到 {}: {}", event.getTableName(), event.getEntity());
} else {
// 插入后
log.info("已插入到 {}: {}", event.getTableName(), event.getEntity());
// 可以在这里发送消息、记录日志等
}
}
@EventListener
public void onUpdate(EntityUpdateByIdEvent event) {
// 处理更新事件
}
@EventListener
public void onDelete(EntityDeleteEvent event) {
// 处理删除事件
}
@EventListener
public void onDeleteBatch(EntityDeleteBatchEvent event) {
// 处理批量删除事件
}
}
```
### 自定义 ID 生成器
```java
@Bean
public IIdGenerator customIdGenerator() {
return () -> {
// 自定义 ID 生成逻辑
return UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE;
};
}
```
### 自定义仓库处理器
```java
@Bean
public IRepositoryHandler customRepositoryHandler(IIdGenerator idGenerator) {
return new DefaultRepositoryHandler(idGenerator) {
@Override
public void fillInsertEntity(BaseEntity entity) {
super.fillInsertEntity(entity);
// 添加自定义字段填充逻辑
// 例如:设置创建人、创建时间等
}
};
}
```
### 缓存配置
框架集成了 J2Cache 二级缓存,需要配置 `j2cache.properties`:
```properties
# 一级缓存
j2cache.L1.provider_class=caffeine
caffeine.region.default=1000,30m
# 二级缓存
j2cache.L2.provider_class=redis
j2cache.L2.config_section=redis
redis.hosts=localhost:6379
redis.password=
redis.database=0
```
## 🔨 本地构建
```bash
# 克隆仓库
git clone https://github.com/talins/mybatis-max.git
cd mybatis-max
# Maven 构建
mvn clean install -DskipTests
# 运行测试
mvn test
```
## 📋 模块说明
| 模块 | 说明 |
|------|------|
| `mybatis-max-api` | 核心接口(`IRepository`、`IRepositoryService`)和 POJO(`BaseEntity`、`Query`、`Condition`) |
| `mybatis-max-sdk` | 核心实现,包括 `BaseRepository`、`DynamicMapperUtil`、缓存工具和事件系统 |
| `mybatis-max-spring-boot-starter` | Spring Boot 自动配置、动态 Mapper 注册和默认 Bean 配置 |
| `mybatis-max-web` | REST 控制器(`BaseRest`),提供所有数据库操作的 HTTP 接口 |
| `mybatis-max-test` | 测试用例和使用示例 |
## 🔍 API 参考
### IRepository 接口
```java
public interface IRepository {
// 插入
Long insert(String tableName, T entity);
// 删除
int deleteById(String tableName, Long id);
int deleteByMap(String tableName, Map columnMap);
int delete(String tableName, QueryWrapper queryWrapper);
int deleteBatchIds(String tableName, Collection idList);
// 更新
int updateById(String tableName, T entity);
int update(String tableName, T entity, QueryWrapper updateWrapper);
// 查询
T selectById(String tableName, Long id, Class clazz);
List selectBatchIds(String tableName, Collection idList, Class clazz);
List selectByMap(String tableName, Map columnMap, Class clazz);
T selectOne(String tableName, QueryWrapper queryWrapper);
List selectList(String tableName, QueryWrapper queryWrapper);
List selectList(String tableName, IPage page, QueryWrapper queryWrapper);
> P selectPage(String tableName, P page, QueryWrapper queryWrapper);
// 统计
Long selectCount(String tableName, QueryWrapper queryWrapper);
boolean exists(String tableName, QueryWrapper queryWrapper);
}
```
### REST API 端点
| 端点 | 方法 | 说明 |
|------|------|------|
| `/mybatis-max/insert/{tableName}` | POST | 插入记录 |
| `/mybatis-max/deleteById/{tableName}` | POST | 根据 ID 删除 |
| `/mybatis-max/deleteByMap/{tableName}` | POST | 根据条件删除 |
| `/mybatis-max/delete/{tableName}` | POST | 根据 QueryWrapper 删除 |
| `/mybatis-max/deleteBatchIds/{tableName}` | POST | 批量删除 |
| `/mybatis-max/updateById/{tableName}` | POST | 根据 ID 更新 |
| `/mybatis-max/update/{tableName}` | POST | 根据条件更新 |
| `/mybatis-max/selectById/{tableName}` | POST | 根据 ID 查询 |
| `/mybatis-max/selectBatchIds/{tableName}` | POST | 批量 ID 查询 |
| `/mybatis-max/selectByMap/{tableName}` | POST | 根据 Map 条件查询 |
| `/mybatis-max/selectOneByMap/{tableName}` | POST | 根据 Map 条件查询单条 |
| `/mybatis-max/selectOne/{tableName}` | POST | 查询单条记录 |
| `/mybatis-max/selectList/{tableName}` | POST | 查询列表 |
| `/mybatis-max/selectPage/{tableName}` | POST | 分页查询 |
| `/mybatis-max/selectCount/{tableName}` | POST | 统计数量 |
| `/mybatis-max/selectCountByMap/{tableName}` | POST | 根据 Map 统计数量 |
| `/mybatis-max/exists/{tableName}` | POST | 判断是否存在 |
## 🤝 参与贡献
欢迎贡献代码!请查看 [贡献指南](CONTRIBUTING.md) 了解详情。
1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/amazing-feature`)
3. 提交更改 (`git commit -m 'Add amazing feature'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 提交 Pull Request
## 📄 开源协议
本项目采用 Apache License 2.0 协议 - 详见 [LICENSE](LICENSE) 文件。
## 🙏 致谢
- [MyBatis-Plus](https://github.com/baomidou/mybatis-plus) - 本项目基于的强大 ORM 框架
- [Hutool](https://github.com/dromara/hutool) - 全面的 Java 工具库
- [J2Cache](https://gitee.com/ld/J2Cache) - 二级缓存框架
- [Yitter IdGenerator](https://github.com/yitter/IdGenerator) - 雪花 ID 生成器
---
Made with ❤️ by Talins