作为一个从业多年的java开发人员,从早期的jdbc拼SQL语法,到后来的hibernate,真是让人眼前一亮,告别了在代码里写一堆字符串拼接的SQL语句,通过Entity对象的操作,就可以实现简单的CRUD操作,确实方便了很,但随着业务的发展,我靠,多表关联,hibernate让人头痛。
冥冥之中,好像上天知道程序员心中之痛,新的ORM框架ibatis,mybatis出现了,可以在xml中编写SQL语句,能更好的处理多表关联的业务了,配合自动生成PO,XML,MAPPER等功能,确实好用了很多,但是很多人又开始吐槽编写SQL语句了,但我觉得最原始才是最好的。
反正各种ORM框架,层出不穷,总有它适应的地方,mybatis-plus,fluent-mybatis,jpa等。
今天又看到一个新的类似ORM的框架,具备了ORM框架的功能,同时也还有一点 GraphQL语法的味道,这个新的框架叫Bean Searcher,gitee地址为:
toscode.gitee.com/ejlchina-zh…
来看看官方的介绍
-
框架目的:只一行代码实现:
-
多表联查
-
分页搜索
-
任意字段组合过滤
-
任意字段排序
-
多字段统计
-
直接得到 VO
(架构图)
✨ 特性
-
支持 实体多表映射
-
支持 动态字段运算符
-
支持 分组聚合 查询
-
支持 Select | Where | From 子查询
-
支持 实体类嵌入参数
-
支持 字段转换器
-
支持 Sql 拦截器
-
支持 数据库 Dialect 扩展
-
支持 多数据源 与 动态数据源
-
支持 注解缺省 与 自定义
-
支持 字段运算符 扩展
-
等等
⁉️为什么用
这绝不是一个重复的轮子
虽然 增删改 是 hibernate 和 mybatis、data-jdbc 等等 ORM 的强项,但查询,特别是有 多条件、联表、分页、排序 的复杂的列表查询,却一直是它们的弱项。
传统的 ORM 很难用较少的代码实现一个复杂的列表检索,但 Bean Searcher 却在这方面下足了功夫,这些复杂的查询,几乎只用一行代码便可以解决。
- 例如,这样的一个典型的需求:
后端需要写一个检索接口,而如果用传统的 ORM 来写,代码之复杂是可以想象的。
而 Bean Searcher 却可以:
💥 只一行代码实现以上功能
首先,你有一个实体类:
@SearchBean(tables="user u, role r", joinCond="u.role_id = r.id", autoMapTo="u")public class User { private long id; private String username; private int status; private int age; private String gender; private Date joinDate; private int roleId; @DbField("r.name") private String roleName; // Getters and setters...}
然后你就可以用一行代码实现这个用户检索接口:
@RestController@RequestMapping("/user")public class UserController { @Autowired private BeanSearcher beanSearcher; // 注入 BeanSearcher 的检索器 @GetMapping("/index") public SearchResult<User> index(HttpServletRequest request) { // 这里只写一行代码 return beanSearcher.search(User.class, MapUtils.flat(request.getParameterMap()), new String[]{ "age" }); } }
这一行代码实现了以下功能:
-
多表联查
-
分页搜索
-
组合过滤
-
任意字段排序
-
字段统计
例如,该接口支持如下请求:
-
GET: /user/index
无参请求(默认分页):
{ "dataList": [ { "id": 1, "username": "Jack", "status": 1, "level": 1, "age": 25, "gender": "Male", "joinDate": "2021-10-01" }, ... // 默认返回 15 条数据 ], "totalCount": 100, "summaries": [ 2500 // age 字段统计 ]}
-
GET: /user/index? page=1 & size=10
指定分页参数
-
GET: /user/index? status=1
返回
status = 1
的用户 -
GET: /user/index? name=Jac & name-op=sw
返回
name
已Jac
开头的用户 -
GET: /user/index? name=Jack & name-ic=true
返回
name = Jack
(忽略大小写)的用户 -
GET: /user/index? sort=age & order=desc
按字段
age
降序查询 -
GET: /user/index? onlySelect=username,age
-
只检索
username
与age
两个字段:{ "dataList": [ { "username": "Jack", "age": 25 }, ... ], "totalCount": 100, "summaries": [ 2500 ]}
-
GET: /user/index? selectExclude=joinDate
检索时排除
joinDate
字段
✨ 参数构建器
Map<String, Object> params = MapUtils.builder() .selectExclude(User::getJoinDate) // 排除 joinDate 字段 .field(User::getStatus, 1) // 过滤:status = 1 .field(User::getName, "Jack").ic() // 过滤:name = 'Jack' (case ignored) .field(User::getAge, 20, 30).op(Opetator.Between) // 过滤:age between 20 and 30 .orderBy(User::getAge, "asc") // 排序:年龄,从小到大 .page(0, 15) // 分页:第 0 页, 每页 15 条 .build();List<User> users = beanSearcher.searchList(User.class, params);
🚀 快速开发
使用 Bean Searcher 可以极大地节省后端的复杂列表检索接口的开发时间!
-
普通的复杂列表查询只需一行代码
-
单表检索可复用原有
Domain
,无需定义SearchBean
🌱 集成简单
可以和任意 Java Web 框架集成,如:SpringBoot、Spring MVC、Grails、Jfinal 等等。
Spring Boot 项目,添加依赖即集成完毕:
implementation 'com.ejlchina:bean-searcher-boot-stater:3.6.1'
接着便可在 Controller
或 Service
里注入检索器:
/** * 注入 Map 检索器,它检索出来的数据以 Map 对象呈现 */@Autowiredprivate MapSearcher mapSearcher;/** * 注入 Bean 检索器,它检索出来的数据以 泛型 对象呈现 */@Autowiredprivate BeanSearcher beanSearcher;
其它框架,使用如下依赖:
implementation 'com.ejlchina:bean-searcher:3.6.1'
然后可以使用 SearcherBuilder
构建一个检索器:
DataSource dataSource = ... // 拿到应用的数据源// DefaultSqlExecutor 也支持多数据源SqlExecutor sqlExecutor = new DefaultSqlExecutor(dataSource);// 构建 Map 检索器MapSearcher mapSearcher = SearcherBuilder.mapSearcher() .sqlExecutor(sqlExecutor) .build();// 构建 Bean 检索器BeanSearcher beanSearcher = SearcherBuilder.beanSearcher() .sqlExecutor(sqlExecutor) .build();
🔨 扩展性强
面向接口设计,用户可自定义扩展 Bean Searcher 中的任何组件!
比如你可以:
-
自定义
FieldOp
来支持更多的字段运算符 -
自定义
FieldConvertor
来支持任意的 特殊字段类型 -
自定义
DbMapping
来实现自定义注解,或让 Bean Searcher 识别其它 ORM 的注解 -
自定义
ParamResolver
来支持其它形式的检索参数 -
自定义
Dialect
来支持更多的数据库 -
等等..
最后
目前只支持简单的 VO 模型,它的设计是面向前端的查询,而不是面向后端的业务,所以开头说有点像graphQL,语法上,支持现在流行的各种数据,只要它是正常的SQL语法。
参考