在国内目前使用最多的ORM框架就是Mybatis-Plus,也不得不承认,Mybatis-Plus相对于JPA而言,也确实好用一些(就个人而言),但是在国外JPA框架还是挺火的,因为JPA是一个完全的ORM框架,而Mybatis-Plus是一个半ORM框架。 但是,在这段时间Apache推出的Mybatis-Flex框架,我个人认为也是Mybatis框架从半ORM转向完整的ORM框架的补充。
既然说MyBatis-Flex是迈向完整的ORM框架,强大的地方肯定不是一星半点,一起来看看吧。
MyBatis-Flex一个优雅的 MyBatis 增强框架,更轻量、更灵活、以及更高的性能。
1、更轻量
MyBatis-Flex 除了 MyBatis 本身,再无任何第三方依赖,因此会带来更高的自主性、把控性和稳定性。在任何一个系统中,依赖越多,稳定性越差。
2、更灵活
MyBatis-Flex 提供了非常灵活的 QueryWrapper,支持关联查询、多表查询、多主键、逻辑删除、乐观锁更新、数据填充、数据脱敏等等。
3、更高的性能
MyBatis-Flex 通过独特的架构,没有任何 MyBatis 拦截器、在 SQL 执行的过程中,没有任何的 SQL Parse,因此会带来指数级的性能增长。
数据库 | 描述 |
---|---|
mysql | MySql 数据库v |
mariadb | MariaDB 数据库 |
oracle | Oracle11g 及以下数据库 |
db2 | DB2 数据库 |
hsql | HSQL 数据库 |
sqlite | SQLite 数据库 |
postgresql | PostgreSQL 数据库 |
sqlserver2005 | SQLServer2005 数据库 |
sqlserver | SQLServer 数据库 |
dm | 达梦数据库 |
xugu | 虚谷数据库 |
kingbasees | 人大金仓数据库 |
phoenix | Phoenix HBase 数据库 |
gauss | Gauss 数据库 |
使用的工具:
user表:
CREATE TABLE `user` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '用户名',
`email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '邮箱',
`phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '手机号',
`type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色',
)
user_address表:
CREATE TABLE `user_address` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`create_user` bigint NOT NULL DEFAULT 0 COMMENT '创建人',
`receive_name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '收货人',
`receive_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '联系号码',
`province` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '省份',
`city` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '城市',
`area` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '区',
PRIMARY KEY (`id`) USING BTREE
)
<dependency>
<groupId>com.mybatis-flexgroupId>
<artifactId>mybatis-flex-spring-boot-starterartifactId>
<version>1.5.6version>
dependency>
<dependency>
<groupId>com.mysqlgroupId>
<artifactId>mysql-connector-jartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>3.0.2version>
dependency>
mybatis-spring-boot-starter这个依赖一定要导入,不然就会报错:
caused by: java.lang.illegalargumentexception: property ‘sqlsessionfactory’ or ‘sqlsessiontemplate’ …
Mybatis-flex在数据访问类上做了修改:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(value = "user_address")
public class UserAddress {
@Id(keyType = KeyType.Auto) // 相当于 @TableId(type = IdType.AUTO)
private int id;
@Column(value = "receive_name")
private String receiveName;
private String receivePhone;
private String province;
private String city;
private String area;
private int createUser;
}
public enum KeyType {
Auto,
Sequence,
Generator,
None;
}
yaml文件:
spring:
datasource:
url: jdbc:mysql://localhost:3306/e-shop
username: root
password: 123456
mybatis-flex:
configuration:
## 显示执行的SQL信息
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
启动类:
@SpringBootApplication
@MapperScan("com.t_time.flex.dao") // 开启Mapper层的Bean扫码
public class MybatisFlexTestApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisFlexTestApplication.class, args);
}
}
查询所有用户信息:
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/user")
public class UserController {
private final UserService userService;
@GetMapping(value = "/all")
public Object all(){
return userService.list();
}
}
因为Mybatis-plus在国内比较火,所以就拿MyBatis-plus与之比较。
MyBatis-Plus:老牌的 MyBatis 增强框架,开源于 2016 年。
Mybatis-plus
LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery()
.like(User::getUsername, "adm")
.or()
.like(User::getEmail, "abc");
userService.list(wrapper);
// 或者
QueryWrapper<User> wrapper = Wrappers.query()
.like(searchWord != null, "last_name", searchWord)
.eq("gender", 1)
.gt("age", 24);
userService.list(wrapper);
Mybatis-Flex
MyBatis-Flex 中的 QueryWrapper 是一个用于构建查询条件的辅助类。它提供了一组方法,可以通过链式调用来添加各种查询条件。
QueryWrapper query = QueryWrapper.create()
.where(USER.USER_NAME.like(searchWord)) //条件为null时自动忽略
.and(USER.GENDER.eq(1))
.and(USER.AGE.gt(24));
List<User> users = userMapper.selectListByQuery(query);
这里使用了Mybatis-flex的一个亮点技术—— APT,这个在之后的文章里会讲。
Mybatis-plus
QueryWrapper<User> queryWrapper = Wrappers.query()
.select(
"id",
"user_name",
);
List<User> users = userMapper.selectList(queryWrapper);
这么写的缺点就是存在硬编码问题,因为是字符串做参数,如果参数 没写正确SQL就会执行错误。
Mybatis-Flex
QueryWrapper query = QueryWrapper.create()
.select(
USER.ID,
USER.USER_NAME,
);
List<User> users = userMapper.selectListByQuery(query);
这里同样使用了APT技术,我们就可以直接用链的方式点出属性,然后由Mybatis-flex对字段进行映射,这样我们如果SQL没有执行成功,也会是映射出现的问题。
Mybatis-plus
QueryWrapper<User> query = Wrappers.query()
.ge("id", 100)
.and(i -> i.eq("sex", 1).or(x -> x.eq("sex", 2)))
.or(i -> i.in("age", 18, 19, 20).like("user_name", "michael"));
// 或者
LambdaQueryWrapper<User> query = Wrappers.<USER>lambdaQuery()
.ge(USER::getId, 100)
.and(i -> i.eq(USER::getSex, 1).or(x -> x.eq(USER::getSex, 2)))
.or(i -> i.in(User::getAge, 18, 19, 20).like(User::getUserName, "michael"));
Mybatis-Flex
QueryWrapper query = QueryWrapper.create()
.where(USER.ID.ge(100))
.and(USER.SEX.eq(1).or(USER.SEX.eq(2)))
.or(USER.AGE.in(18, 19, 20).and(USER.USER_NAME.like("michael")));
亮点来了,MyBatis-plus是不支持代码层面的多表联合的,但是,MyBatis-flex做到了,它可以实现代码层面的多表联合。
QueryWrapper query = QueryWrapper.create()
.select().from(ACCOUNT)
.leftJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.where(ACCOUNT.AGE.ge(10));
List<Account> accounts = mapper.selectListByQuery(query);
语法:leftJoin(表对象).on(条件)
在SQL中我们有时也不适用leftJoin等其他关键字,就是直接在FROM后面接多个表,用逗号隔开。
SELECT a.id, a.user_name, b.id AS addressId, b.province
FROM user AS a, user_address AS b
WHERE a.id = b.create_id
QueryWrapper query = new QueryWrapper()
.select(
USER.ID
, USER.USER_NAME
, USERADDRESS.ID.as("addressId")
, USERADDRESS.PROVINCE)
.from(ACCOUNT.as("a"), ARTICLE.as("b"))
.where(USER.ID.eq(USERADDRESS.CREATE_ID));
在更新字段上,基本上的逻辑都是相同的。
MyBatis-plus
LambdaUpdateWrapper<User> wrapper = Wrappers.<User>lambdaUpdate()
.eq(User::getId, "001")
.set(User::getUsername, "李四");
userService.update(wrapper);
MyBatis-Flex
Account account = UpdateEntity.of(Account.class);
account.setId(100); //设置主键
account.setUserName("michael");
account.setAge(18);
account.setBirthday(null);
accountMapper.update(account);
就我个人而言,Mybatis-Flex在使用中确实让开发者脱离的XML文件,但是,也让Java代码变得非常的庞大,在多个表进行连接的时候就会出现一连串很长的Java代码,也让阅读性变差了。
总体初步而言,有好也有差吧。