框架介绍
MyBatis-Flex 是一个优雅的 MyBatis 增强框架,它非常轻量、同时拥有极高的性能与灵活性。
说明
本文参照官方文档的【快速开始】 章节,编写 Spring Boot 项目的代码示例。
快速开始
创建数据库表
直接参照官网示例,SQL如下:
CREATE TABLE IF NOT EXISTS `tb_account`
(
`id` INTEGER PRIMARY KEY auto_increment,
`user_name` VARCHAR(100),
`age` INTEGER,
`birthday` DATETIME
);
INSERT INTO tb_account(id, user_name, age, birthday)
VALUES (1, '张三', 18, '2020-01-11'),
(2, '李四', 19, '2021-03-21');
依赖
MyBatis-Flex 核心依赖
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.7.3</version>
</dependency>
<!-- 数据库连接池依赖必须添加,否则会报错 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.20</version>
</dependency>
驱动依赖(MySQL)
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
其余依赖,比如 Lombok,spring-boot-starter-web,spring-boot-starter-test,此处省略。
数据源配置
SpringBoot 原生配置
application.yml
中添加数据源配置。
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis-flex
username: root
password: password
type: com.alibaba.druid.pool.DruidDataSource
因为使用了 Druid,所以必须配置 type
。
MyBatis-Flex 配置方式(支持多数据源)
mybatis-flex:
datasource:
# 数据源的名称(用户自定义)
data-source-1:
url: jdbc:mysql://localhost:3306/mybatis-flex
username: root
password: password
不再需要写 type 了,mybatis-flex 框架会自动识别项目中的 数据库连接池。如果不同的数据源,使用不同的连接池,也可以每个数据源配置 type。
APT 配置
MyBatis-Flex APT 配置
MyBatis-Flex 使用了 APT(Annotation Processing Tool)技术,在项目编译的时候,会自动根据 Entity 类定义的字段帮你生成 “ACCOUNT” 类以及 Entity 对应的 Mapper 类, 通过开发工具构建项目(如下图),或者执行 maven 编译命令: mvn clean package 都可以自动生成。这个原理和 lombok 一致。
要对 MyBatis-Flex 的 APT 细节选项进行配置,你需要在项目的 根目录 ( pom.xml 所在的目录)下创建名为 mybatis-flex.config 的文件。
配置文件:mybatis-flex.config
# 开启 Mapper 自动生成
processor.mapper.generateEnable = true
# 开启 @Mapper 注解
processor.mapper.annotation = true
配置文件图片示例
实体类和Mapper
实体类
这里使用了 Lombok 来简化代码。
package com.example.db.mybatisflex.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 账户 实体类。
*
* @author 宋冠巡
* @since 2023-10-29
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(value = "tb_account")
public class Account implements Serializable {
@Id(keyType = KeyType.Auto)
private Integer id;
private String userName;
private Integer age;
private LocalDateTime birthday;
}
Mapper
Mapper 使用APT技术,编译之后自动生成,示例如下:
测试
package com.example;
import com.example.db.mybatisflex.entity.Account;
import com.example.db.mybatisflex.mapper.AccountMapper;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static com.example.db.mybatisflex.entity.table.AccountTableDef.ACCOUNT;
@Slf4j
@SpringBootTest
class MybatisFlexDemoApplicationTests {
private final AccountMapper accountMapper;
@Autowired
public MybatisFlexDemoApplicationTests(AccountMapper accountMapper) {
this.accountMapper = accountMapper;
}
@Test
void contextLoads() {
QueryWrapper queryWrapper = QueryWrapper.create()
.select()
.where(ACCOUNT.AGE.eq(18));
Account account = accountMapper.selectOneByQuery(queryWrapper);
log.info("accounts = {}", account);
}
}
控制台输出:
accounts = Account(id=1, userName=张三, age=18, birthday=2020-01-11T00:00)
代码生成器
使用 代码生成器
,根据数据库逆向生成 实体类
和 Service
。
生成的位置:生成器类 所在目录,作为根目录。
依赖
<!-- 代码生成器 -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId>
<version>1.7.3</version>
</dependency>
<!-- 加入代码生成器后,只有加入 processor 依赖,才能正常使用 APT。-->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.7.3</version>
<scope>provided</scope>
</dependency>
代码生成器 - 代码
package com.example.db.mybatisflex;
import com.alibaba.druid.pool.DruidDataSource;
import com.mybatisflex.codegen.Generator;
import com.mybatisflex.codegen.config.GlobalConfig;
public class Codegen {
public static void main(String[] args) {
// 配置数据源
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis-flex");
dataSource.setUsername("root");
dataSource.setPassword("password");
// 创建配置内容
GlobalConfig globalConfig = createGlobalConfigUseStyle1();
// 通过 datasource 和 globalConfig 创建代码生成器
Generator generator = new Generator(dataSource, globalConfig);
// 生成代码
generator.generate();
}
public static GlobalConfig createGlobalConfigUseStyle1() {
// 创建配置内容
GlobalConfig globalConfig = new GlobalConfig();
// 设置作者
globalConfig.setAuthor("宋冠巡");
// 设置根包
globalConfig.setBasePackage("com.example.db.mybatisflex");
// 设置表前缀和只生成哪些表
globalConfig.setTablePrefix("tb_");
globalConfig.setGenerateTable("tb_account");
// 设置生成 entity 并启用 Lombok
globalConfig.setEntityGenerateEnable(true);
globalConfig.setEntityWithLombok(true);
// 设置生成 mapper :如果使用 APT 生成 mapper,则可以不用由代码生成器来生成。
// globalConfig.setMapperGenerateEnable(true);
// 设置生成 service
globalConfig.setServiceGenerateEnable(true);
globalConfig.setServiceImplGenerateEnable(true);
return globalConfig;
}
}
生成效果
SQL 日志打印
内置方案
package com.example.db.config;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.audit.MessageCollector;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisFlexConfiguration {
public MyBatisFlexConfiguration() {
// 开启审计功能
AuditManager.setAuditEnable(true);
// 设置 SQL 审计收集器
MessageCollector collector = new ConsoleMessageCollector();
AuditManager.setMessageCollector(collector);
}
}
MyBatis 自带方案
application.yml
中添加配置。
mybatis-flex:
configuration:
# 打印SQL日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
Mapper 链式操作
package com.example;
import com.example.db.mybatisflex.entity.Account;
import com.example.db.mybatisflex.mapper.AccountMapper;
import com.mybatisflex.core.query.QueryChain;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static com.example.db.mybatisflex.entity.table.AccountTableDef.ACCOUNT;
@Slf4j
@SpringBootTest
class ChainTest {
private final AccountMapper accountMapper;
@Autowired
public ChainTest(AccountMapper accountMapper) {
this.accountMapper = accountMapper;
}
@Test
void testChain() {
List<Account> accounts = QueryChain.of(accountMapper)
.select(ACCOUNT.ALL_COLUMNS)
.from(ACCOUNT)
.where(ACCOUNT.AGE.ge(18))
.list();
log.info("accounts = {}", accounts);
}
}
Service 链式操作
package com.example;
import com.example.db.mybatisflex.entity.Account;
import com.example.db.mybatisflex.service.AccountService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static com.example.db.mybatisflex.entity.table.AccountTableDef.ACCOUNT;
/**
* 测试 Service
*/
@Slf4j
@SpringBootTest
class ServiceTest {
private final AccountService accountService;
@Autowired
public ServiceTest(AccountService accountService) {
this.accountService = accountService;
}
/**
* 测试 Service 的 链式操作
*/
@Test
void testServiceQueryChain() {
List<Account> accounts = accountService.queryChain()
.select(ACCOUNT.ALL_COLUMNS)
.from(ACCOUNT)
.where(ACCOUNT.AGE.ge(18))
.list();
log.info("accounts = {}", accounts);
}
}