区别一(基本)
Mybatis Plus 依赖 MyBatis, 功能 CRUD 都有,而 Bean Seracher 不依赖任何 ORM,只专注高级查询。
只有使用 MyBatis 的项目才会用 Mybatis Plus,而使用 Hibernate,Data Jdbc 等其它 ORM 的人则无法使用 Mybatis Plus。但是这些项目都可以使用 Bean Searcher(可与任何 ORM 配合使用,也可单独使用)。
使用 Mybatis Plus 需要编写实体类 和 Mapper 接口,而 Bean Searcher 只需编写 实体类,无需编写任何接口。
这个区别意义其实不大,因为如果你用 Mybatis Plus,在增删改的时候还是需要定义 Mapper 接口。
区别二(高级查询)
Mybatis Plus 的 字段运算符 是静态的,而 Bean Searcher 的是动态的。
字段运算符指的是某字段参与条件时用的是 =
、>
亦或是 like
这些条件类型。
不只 Mybatis Plus,一般的传统 ORM 的字段运算符都是静态的,包括 Hibernate、Spring data jdbc、JOOQ 等。
下面举例说明。对于只有三个字段的简单实体类:
public class User {
private long id;
private String name;
private int age;
// 省略 Getter Setter
}
复制代码
1)使用 MyBatis Plus 查询:
依赖:
implementation 'com.baomidou:mybatis-plus-boot-starter:3.5.1
复制代码
首先要写一个 Mapper 接口:
public interface UserMapper extends BaseMapper<User> {
}
复制代码
然后在 Controller 里写查询接口:
("/user")
public class UserController {
private UserMapper userMapper;
("/mp")
public List<User> mp(User user) {
return userMapper.selectList(new QueryWrapper<>(user));
}
}
复制代码
此时这个接口可以支持 三个检索参数,id, name, age,例如:
- GET /user/mp? name=Jack查询 name 等于 Jack 的数据
- GET /user/mp? age=20查询 age 等于 20 的数据
但是他们所能表达的关系都是 等于,如果你还想查询 age > 20 的数据,则无能为力了,除非在实体类的 age 字段上加上一条注解:
condition = "%s>#{%s}")
private int age;
复制代码
(
但加了注解后,age 就 只能 表达 大于 的关系了,不再可以表达 等于了。所以说,MyBatit Plus 的 字段运算符 是 静态 的,不能由参数动态指定。
当然我们可以在 Controller 里增加代码让它支持,但这样代码就不只一行了,检索的需求越复杂,需要编写的代码就越多了。
2)使用 Bean Searcher 查询:
依赖:
implementation 'com.ejlchina:bean-searcher-boot-starter:3.6.0'
复制代码
不用编写任何接口,复用同一个实体类,直接进行查询:
("/user")
public class UserController {
private BeanSearcher beanSearcher;
("/bs")
public List<User> bs( Map<String, Object> params) {
// 你是否对入参 Map 有偏见?如果有,请耐心往下看,有方案
return beanSearcher.searchList(User.class, params);
}
}
复制代码
此时这个接口可以支持的检索参数就非常多了:
- GET /user/bs? name=Jack查询 name 等于 Jack 的数据
- GET /user/bs? name=Jack & name-ic=true查询 name 等于 Jack 时 忽略大小写
- GET /user/bs? name=Jack & name-op=ct查询 name 包含 Jack 的数据
- GET /user/bs? age=20查询 age 等于 20 的数据
- GET /user/bs? age=20 & age-op=gt查询 age 大于 20 的数据
- 等等...
可以看出,Bean Searcher 对每个字段使用的 运算符 都可以由参数指定,它们是 动态 的。
无论查询需求简单还是复杂,Controller 里都只需一行代码。
参数 xxx-op
可以传哪些值?参阅这里:searcher.ejlchina.com/guide/lates…
看到这里,如果看的明白,应该有一半的读者开始感慨:好家伙,这不是把后端组装查询条件的过程都甩给了前端?谁用了这个框架,不会被前端打死吗?
哈哈,我是不是道出了你现在心里的想法?如果你真的如此想,请仔细回看我们正在讨论的主题:【高级查询】!
如果 不能理解什么是高级查询,我再贴个图助你思考:
当然也并不是所有的检索需求都如此复杂,当前端不需要控制检索方式时,xxx-op
参数 可以省略,省略时,默认表达的是 等于,如果你想表达 其它方式,只需一个注解即可,例如:
onlyOn = GreaterThan.class)
private int age;
复制代码
(
这时,当前端只传一个 age
参数时,执行的 SQL 条件就是 age > ?
了,并且即使前端多传一个 age-op
参数,也不再起作用了。
这其实是条件约束,下文会继续讲到。
区别三(逻辑分组)
就上文所例的代码,除却运算符 动静 的区别,Mybatis Plus 对接收到的参数生成的条件 都是且的关系,而 Bean Searcher 默认也是且,但支持 逻辑分组。
再举例说明,假设查询条件为:
( name = Jack 并且 age = 20 ) 或者 ( age = 30 )
此时,MyBatis Plus 的一行代码就无能为力了,但 Bean Searcher 的一行代码仍然管用,只需这样传参即可:
- GET /user/bs? a.name=Jack & a.age=20 & b.age=30 & gexpr=a|b
这里 Bean Searcher 将参数分为 a
, b
两组,并用新参数 gexpr
来表达这两组之间的关系(a
或 b
)。
实际传参时gexpr
的值需要 URLEncode 编码一下: URLEncode('a|b') => 'a%7Cb',因为 HTTP 规定参数在 URL 上不可以出现 |
这种特殊字符。当然如果你喜欢 POST, 可以将它放在报文体里。