Mybatis-Flex 一个优雅的 Mybatis 增强框架
Mybatis-Flex: 更灵活、更轻量、更好用
特征
- 很轻量,整个框架只依赖 Mybatis 再无其他第三方依赖
- 只增强,支持 Entity 的增删改查、及分页查询,但不丢失 Mybatis 原有功能
- 内置 Db + Row 工具,可以无需实体类对数据库进行增删改查
- 支持多种数据库类型,还可以通过方言持续扩展
- 支持多(联合)主键,以及不同的主键内容生成策略
- 支持逻辑删除设置、更新或插入的默认值配置以及大字段等设置
- 支持乐观锁字段配置,在数据更新时自动进行乐观锁检测
- 极其友好的 SQL 联动查询,IDE 自动提示不再担心出错
快速开始
Maven 依赖
以下的 xml maven 依赖示例中,可能并非最新的 Mybatis-Flex 版本,请自行查看最新版本,并修改版本号。
1、只用到了 Mybatis,没用到 Spring 的场景:
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.0.2</version>
</dependency>
2、用到了 Spring 的场景
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId>
<version>1.0.2</version>
</dependency>
3、用到了 Spring Boot 的场景
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.0.2</version>
</dependency>
hello world(原生)
第一步:编写 Entity 实体类
@Table("tb_account")
public class Account {
@Id(keyType = KeyType.Auto)
private Long id;
private String userName;
private Date birthday;
private int sex;
//getter setter
}
第二步,编写 Mapper 类,并继承 BaseMapper
public interface AccountMapper extends BaseMapper<Account> {
//只需定义 Mapper 接口即可,可以无任何内容。
}
第三步:开始查询数据
示例 1:查询 1 条数据
class HelloWorld {
public static void main(String... args) {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/mybatis-flex");
dataSource.setUsername("username");
dataSource.setPassword("password");
MybatisFlexBootstrap.getInstance()
.setDatasource(dataSource)
.addMapper(AccountMapper.class)
.start();
//示例1:查询 id=100 条数据
Account account = MybatisFlexBootstrap.getInstance()
.execute(AccountMapper.class, mapper ->
mapper.selectOneById(100)
);
}
}
示例2:查询列表
//示例2:通过 QueryWrapper 构建条件查询数据列表
QueryWrapper query=QueryWrapper.create()
.select()
.from(ACCOUNT)
.where(ACCOUNT.ID.ge(100))
.and(ACCOUNT.USER_NAME.like("张").or(ACCOUNT.USER_NAME.like("李")));
// 执行 SQL:
// ELECT * FROM tb_account
// WHERE tb_account.id >= 100
// AND (tb_account.user_name LIKE '%张%' OR tb_account.user_name LIKE '%李%' )
List<Account> accounts = MybatisFlexBootstrap.getInstance()
.execute(AccountMapper.class,mapper->
mapper.selectListByQuery(query)
);
示例3:分页查询
// 示例3:分页查询
// 查询第 5 页,每页 10 条数据,通过 QueryWrapper 构建条件查询
QueryWrapper query=QueryWrapper.create()
.select()
.from(ACCOUNT)
.where(ACCOUNT.ID.ge(100))
.and(ACCOUNT.USER_NAME.like("张").or(ACCOUNT.USER_NAME.like("李")))
.orderBy(ACCOUNT.ID.desc());
// 执行 SQL:
// ELECT * FROM tb_account
// WHERE id >= 100
// AND (user_name LIKE '%张%' OR user_name LIKE '%李%' )
// ORDER BY `id` DESC
// LIMIT 40,10
Page<Account> accounts = MybatisFlexBootstrap.getInstance()
.execute(AccountMapper.class,mapper->
mapper.paginate(5,10,query)
);
QueryWrapper示例
select *
QueryWrapper query=new QueryWrapper();
query.select().from(ACCOUNT)
// SQL:
// SELECT * FROM tb_account
select columns
简单示例:
QueryWrapper query=new QueryWrapper();
query.select(ACCOUNT.ID,ACCOUNT.USER_NAME)
.from(ACCOUNT)
// SQL:
// SELECT id, user_name
// FROM tb_account
多表查询(同时展现了功能强大的 as 能力):
QueryWrapper query = new QueryWrapper()
.select(ACCOUNT.ID
, ACCOUNT.USER_NAME
, ARTICLE.ID.as("articleId")
, ARTICLE.TITLE)
.from(ACCOUNT.as("a"), ARTICLE.as("b"))
.where(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID));
// SQL:
// SELECT a.id, a.user_name, b.id AS articleId, b.title
// FROM tb_account AS a, tb_article AS b
// WHERE a.id = b.account_id
select functions
QueryWrapper query=new QueryWrapper()
.select(
ACCOUNT.ID,
ACCOUNT.USER_NAME,
max(ACCOUNT.BIRTHDAY),
avg(ACCOUNT.SEX).as("sex_avg")
).from(ACCOUNT);
// SQL:
// SELECT id, user_name,
// MAX(birthday),
// AVG(sex) AS sex_avg
// FROM tb_account
where
QueryWrapper queryWrapper=QueryWrapper.create()
.select()
.from(ACCOUNT)
.where(ACCOUNT.ID.ge(100))
.and(ACCOUNT.USER_NAME.like("michael"));
// SQL:
// SELECT * FROM tb_account
// WHERE id >= ?
// AND user_name LIKE ?
where select
QueryWrapper queryWrapper = QueryWrapper.create()
.select()
.from(ACCOUNT)
.where(ACCOUNT.ID.ge(
select(ARTICLE.ACCOUNT_ID).from(ARTICLE).where(ARTICLE.ID.ge(100))
));
// SQL:
// SELECT * FROM tb_account
// WHERE id >=
// (SELECT account_id FROM tb_article WHERE id >= ? )
and (...) or (...)
QueryWrapper queryWrapper=QueryWrapper.create()
.select()
.from(ACCOUNT)
.where(ACCOUNT.ID.ge(100))
.and(ACCOUNT.SEX.eq(1).or(ACCOUNT.SEX.eq(2)))
.or(ACCOUNT.AGE.in(18,19,20).and(ACCOUNT.USER_NAME.like("michael")));
// SQL:
// SELECT * FROM tb_account
// WHERE id >= ?
// AND (sex = ? OR sex = ? )
// OR (age IN (?,?,?) AND user_name LIKE ? )
group by
QueryWrapper queryWrapper=QueryWrapper.create()
.select()
.from(ACCOUNT)
.groupBy(ACCOUNT.USER_NAME);
// SQL:
// SELECT * FROM tb_account
// GROUP BY user_name
having
QueryWrapper queryWrapper=QueryWrapper.create()
.select()
.from(ACCOUNT)
.groupBy(ACCOUNT.USER_NAME)
.having(ACCOUNT.AGE.between(18,25));
// SQL:
// SELECT * FROM tb_account
// GROUP BY user_name
// HAVING age BETWEEN ? AND ?
orderBy
QueryWrapper queryWrapper=QueryWrapper.create()
.select()
.from(ACCOUNT)
.orderBy(ACCOUNT.AGE.asc()
, ACCOUNT.USER_NAME.desc().nullsLast());
// SQL:
// SELECT * FROM tb_account
// ORDER BY age ASC, user_name DESC NULLS LAST
join
QueryWrapper queryWrapper=QueryWrapper.create()
.select()
.from(ACCOUNT)
.leftJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.innerJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.where(ACCOUNT.AGE.ge(10));
// SQL:
// SELECT * FROM tb_account
// LEFT JOIN tb_article ON tb_account.id = tb_article.account_id
// INNER JOIN tb_article ON tb_account.id = tb_article.account_id
// WHERE tb_account.age >= ?
Mybatis-Flex 乐观锁
使用场景
用于当有多个用户(或者多场景)去同时修改同一条数据的时候,只允许有一个修改成功。
实现原理
使用一个字段,用于记录数据的版本,当修改数据的时候,会去检测当前版本是否是正在修改的版本,同时修改成功后会把 版本号 + 1。
更新数据时,执行的 SQL 如下:
UPDATE account SET nickname = ?, version = version + 1
WHERE id = ? AND version = ?
在以上的 SQL 中,若两个场景同时读取的是同一个 version 的内容,那么必然只最优先执行的 SQL 执行成功。
以下是 示例代码:
@Table("tb_account")
public class Account {
@Column(version = true)
private Long version;
//Getter Setter...
}
需要注意的是:
- 1、在同一张表中,只能有一个被 @Column(version = true) 修饰的字段。
- 2、Account 在插入数据时,若 version 未设置值,那么会自动被 Mybatis-Flex 设置为 0。
-END-
开源协议:Apache-2.0
开源地址:
https://github.com/mybatis-flex/mybatis-flex
JUST DO IT!