Skip to content

Xbatis 和同类框架「功能」对比 ​

Xbatis 主要是和 MyBatis-Plus 对比,内容来源其官网、git 或者 网络文章,若有错误欢迎纠正。

  • MyBatis-Plus:一个流行多年的基于mybatis ORM框架。
  • Xbatis:一个全新的的基于mybatis ORM框架,旨在更方便 更好用 更简单 更省事 更快捷。

本文档只是纯粹比较,无恶意抹黑(更多的是比没有的功能);MyBatis-Plus 还是非常优秀的;只是xbatis是后来者,也有自己的想法和设计。 若发现对比中有错误,请加入 Xbatis QQ 交流群,然后联系群主纠正。

功能对比 ​

功能或特点XbatisMyBatis-Plus
对 entity 的基本增删改查✅✅
分页查询✅✅
子查询分页查询✅❌
分页查询无 SQL 解析设计(更轻量,及更高性能)✅❌
单表查询: from 单表✅✅
多表查询: from 多张表✅❌
多表查询: left join、inner join 等等✅❌
多表查询: union,union all✅❌
ID自增配置✅✅
不同数据库,不同ID自增配置✅❌
支持多主键、复合主键✅❌
字段的 typeHandler 配置✅✅
非实体类 typeHandler 复用✅❌
数据填充✅✅
基于结果Fetch另外表数据✅❌
多租户✅✅
动态分表(更简单)✅✅
一键忽略参数null,空字符串参数的条件拼接✅❌
局部SQL模板(select /where gourpby / having / order by )✅❌
乐观锁✅✅
不同数据库不同SQL(支持局部)✅❌
逻辑删除✅✅
查询结果支持自定义数据库注入(枚举名,其他等等)✅❌
根据返回结果 自动select列✅❌
多表查询结果自动映射(超简单)✅❌
查询结果支持多层嵌套结构✅❌
逻辑删除支持,除flag字段外,任意字段set update✅❌
支持丰富的对象转条件✅❌
支持大部分不同数据的通用函数✅❌
支持mapKey cursor(非原生mybatis)✅❌
支持Mapper方法拦截器✅❌
单个Mapper模式(一个Mapper走天下)✅❌
重复新增/修改策略支持(可以忽略,重复可只修改指定字段)✅❌
支持查询设置查询timeout,fetchsize 配置✅❌
支持查询SQL优化开关(join orderby 都有开关,非全局)✅❌
支持update delete returning操作✅❌

以上内容来自第三方相关产品的官方文档或第三方平台,若有错误,欢迎纠正。

基础查询 ​

Xbatis:

java
 
List<Employee> employees = QueryChain.of(employeeMapper)
        .like(StringUtils.isNotEmpty(searchWord), Employee::getUserName,"B")
        .eq(Employee::getGender, 1)
        .gt(Employee::getAge, 24)
        .list()
        ;

MyBatis-Plus:

java
LambdaQueryWrapper<Employee> queryWrapper = Wrappers.<Employee>lambdaQuery()
        .like(StringUtils.isNotEmpty(searchWord), Employee::getUserName,"B")
        .eq(Employee::getGender, 1)
        .gt(Employee::getAge, 24);
List<Employee> employees = employeeMapper.selectList(queryWrapper);

查询集合函数 ​

Xbatis:

java
List<Employee> employees = QueryChain.of(employeeMapper)
        .select(Employee::getId)
        .select(Employee::getUserName,c->c.max())
        .select(Employee::getBirthday,c->c.max())
        .select(Employee::getBirthday,c->c.avg().as("sex_avg")) 
        .list()
        ;

MyBatis-Plus:

java
QueryWrapper<Employee> queryWrapper = Wrappers.query()
    .select(
        "id",
        "user_name",
        "max(birthday)",
        "avg(birthday) as sex_avg"
    );
List<Employee> employees = employeeMapper.selectList(queryWrapper);

缺点:min max avg等函数硬编码,容易拼错。无法使用 ide 的字段进行重构,无法使用 IDE 自动提示,发生错误不能及时发现。

and(...) 和 or(...) ​

假设我们要构建如下的 SQL 进行查询(需要在 SQL 中添加括号)。

sql
SELECT * FROM tb_account
WHERE id >= 100
AND (sex = 1 OR sex = 2)
OR (age IN (18,19,20) AND user_name LIKE "%michael%" )

Xbatis:

java
List<Employee> employees = QueryChain.of(employeeMapper)
        .gte(Employee::getId, 100)
        .nested(i -> {
            i.eq(Employee::getSex, 1)
            .or()
            .eq(Employee::getSex, 2);
        })
        .or()
        .nested(i -> {
            i.in(Employee::getAge, 18, 19, 20).
            like(Employee::getUserName, "michael");
        });

MyBatis-Plus:

java
LambdaQueryWrapper<Employee> query = Wrappers.<Employee>lambdaQuery()
        .ge(Employee::getId, 100)
        .and(i -> i.eq(Employee::getSex, 1).or(x -> x.eq(Employee::getSex, 2)))
        .or(i -> i.in(Employee::getAge, 18, 19, 20).like(Employee::getUserName, "michael"));

多表查询 ​

Xbatis:

java
Pager<SysUser> pager= QueryChain.of(sysUserMapper)
        .join(SysUser::getRoleId, SysRole::getId)
        .like(SysUser::getUserName,"abc")
        .paging(Pager.of(1));

MyBatis-Plus:

java
// 不支持~~~~

部分字段更新 ​

假设一个实体类 Account 中,我们要更新其内容如下:

  • userName 为 "michael"
  • age 为 "18"
  • birthday 为 null

其他字段保持数据库原有内容不变,要求执行的 SQL 如下:

sql
update tb_account
set user_name = "michael", age = 18, birthday = null
where id = 100

Xbatis 代码如下:

java
Account account = UpdateEntity.of(Account.class);
account.setId(100); //设置主键
account.setUserName("michael");
account.setAge(18);
account.setBirthday(null);

accountMapper.update(account,Account::getBirthday);

MyBatis-Plus 代码如下(或可使用 MyBatis-Plus 的 LambdaUpdateWrapper):

java
LambdaUpdateWrapper<Account> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(Account::getId, 100);
updateWrapper.set(Account::getUserName, "xxx");
updateWrapper.set(Account::getAge, 18);
if (account.getBirthday() != null) {
    updateWrapper.set(Account::getBirthday, account.getBirthday());
} else{
    updateWrapper.setSql("birthday=NULL");    
}
accountMapper.update(null, updateWrapper);

plus 目前只能写sql把 birthday 设置为null

如果有对比不确准的 可以联系我修正,对比抱歉