起步
安装
Maven
<dependency>
<groupId>com.ejlchina</groupId>
<artifactId>bean-searcher</artifactId>
<version>2.2.0</version>
</dependency>
2
3
4
5
Gradle
implementation 'com.ejlchina:bean-searcher:2.2.0'
集成
通常情况下,我们都是在一个后端的 Java Web 项目中使用 Bean Searcher,它可以在任意的 Web 框架中使用,以下介绍在常见的几种 Web 框架的集成方法:
Spring Boot
由于 Bean Searcher 自 v2.0 起就已实现了 Spring Boot Starter 化,所以在 Spring Boot Web 项目中集成 Bean Searcher 最为简单,只需要在应用的配置文件内配置 Search Bean 实体类的包名路径即可,例如在 src/main/resources/application.properties
文件中:
bean-searcher.packages = com.example.sbean
其中 com.example.sbean
为 Search Bean 实体类所在的包名路径,可配多个。
Spring MVC
在传统的 Spring MVC 项目中集成 Bean Searcher 需要在项目的 xml 文件内配置以下两个 Bean:
<bean id="searchSqlExecutor"
class="com.ejlchina.searcher.implement.MainSearchSqlExecutor"
p:dataSource-ref="dataSource" />
<bean id="searcher"
class="com.ejlchina.searcher.support.spring.SpringSearcher"
p:searchSqlExecutor-ref="searchSqlExecutor"
p:scanPackages="{'com.example.sbean'}" />
2
3
4
5
6
7
8
其中com.example.sbean
为 Search Bean 实体类的包名路径,可配多个。
Grails
在 Grails 项目中集成 Bean Searcher,只需要在 grails-app/conf/spring/resources.groovy
文件内配置一个 Bean 即可:
searcher(SpringSearcher) {
scanPackages = [
'com.example.sbean'
]
searchSqlExecutor = { MainSearchSqlExecutor e ->
dataSource = ref('dataSource')
}
}
2
3
4
5
6
7
8
其中com.example.sbean
为 Search Bean 实体类的包名路径,可配多个。
Jfinal
在 Jfinal 项目中集成 Bean Searcher,需要在配置插件的地方配置 SearchPlugin,例如:
public class App extends JFinalConfig implements SearcherReceiver, SearcherConfiger {
@Override
public void configPlugin(Plugins me) {
// 首先获得一个 IDataSourceProvider 实例,比如 DruidPlugin 插件
DruidPlugin dp = new DruidPlugin(...);
// 省略 DruidPlugin 相关的配置
// Bean Searcher 插件,第一个参数接收 IDataSourceProvider 实例
// 第二个参数为 Search Bean 实体类的包名路径,可配多个
SearchPlugin sp = new SearchPlugin(dp, "com.example.sbean");
sp.setSearcherReceiver(this);
sp.setSearcherConfiger(this);
me.add(dp);
me.add(sp);
// 省略其它配置
}
@Override
public void receive(Searcher searcher) {
// 接收到 searcher 实例,可以用一个容器接收,留待后续使用
Ioc.add(Searcher.class, searcher);
}
@Override
public void config(SearcherBuilder builder) {
// TODO: 这里可以对 Bean Searcher 做一些自定义配置
}
// 省略 Jfinal 的其它配置
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
其中com.example.sbean
为 Search Bean 实体类的包名路径,可配置多个。
Others
在其它任意的 Java 项目中,都可以使用如下方法使用 Bean Searcher :
1、启动 Bean Searcher
SearcherStarter starter = new SearcherStarter();
// 传入 Search Bean 实体类的包名(可传多个),并启动
starter.start("com.example.sbean");
2
3
2、构建 Searcher 实例
// 获取配置好的数据源
DataSource dataSource = getDataSource();
// 构建 Searcher 实例
Searcher searcher = SearcherBuilder.builder()
.configSearchSqlExecutor(new MainSearchSqlExecutor(dataSource))
.build();
2
3
4
5
6
得到 Searcher
实例后,便可以在项目中使用它了。
3、停止 Bean Searcher
当项目停止时,可调用 SearcherStarter
对象的 shutdown
方法优雅关闭:
// 关闭检索器
starter.shutdown();
2
使用
Searcher
当在项目中成功集成后,接下来便可以在我们的业务代码中拿到 Searcher
实例了。
Spring Boot、Spring MVC:
// 可以使用注解注入
@Autowired
private Searcher searcher;
2
3
Grails:
// 直接按名称注入
def searcher;
2
Jfinal:
// 从容器里取出
private Searcher searcher = Ioc.get(Searcher.class);
2
编写实体类
然后便是定义检索实体类了,即 SearchBean
,一个简单的 SearchBean
如下所示:
package com.example.sbean;
import com.ejlchina.searcher.bean.SearchBean;
import com.ejlchina.searcher.bean.DbField;
@SearchBean(tables = "user")
public class User {
@DbField("id")
private Long id;
@DbField("name")
private String name;
@DbField("age")
private int age;
// Getter and Setter ...
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
如上:使用 @SearchBean
与 @DbField
注解指定实体类与数据库表以及字段之间的映射关系。需要注意的是:实体类必须定义在 集成 Bean Searcher 时指定的 包路径下。
本例是一个简单的单表检索实体类,更多复杂的联表实体类请参考 实体类 > 多表关联 章节。
开始检索
编写好实体类后,我们便可以尽情地检索了, 首先我们看一下 Searcher
接口提供了哪些方法:
search(Class<T> beanClass, Map<String, Object> params)
适合需要分页的查询;search(Class<T> beanClass, Map<String, Object> params, String[] summaryFields)
适合需要分页与统计的查询;searchFirst(Class<T> beanClass, Map<String, Object> params)
查询满足条件的的第一个 BeansearchList(Class<T> beanClass, Map<String, Object> params)
只检索 Bean 列表,不返回满足条件的总条数searchAll(Class<T> beanClass, Map<String, Object> params)
检索满足条件的所有 Bean,不分页searchCount(Class<T> beanClass, Map<String, Object> params)
只查询满足条件的 Bean 个数searchSum(Class<T> beanClass, Map<String, Object> params, String field)
检索某个字段的统计值searchSum(Class<T> beanClass, Map<String, Object> params, String[] fields)
检索多个字段的统计值
完整的接口定义,可查看代码仓库中的 Searcher 文件。
例如,分页查询用户列表:
Map<String, Object> params = new HashMap<>();
params.put("page", 0); // 第 0 页
params.put("size", 15); // 每页 15 条
SearchResult<User> result = searcher.search(User.class, params);
List<User> users = result.getDataList(); // 第 0 页的用户
Number totalCount = result.getTotalCount(); // 数据总条数
2
3
4
5
6
使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.page(0, 15) // 第 0 页, 每页 15 条
.build();
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
分页查询年龄等于 20 的用户列表:
Map<String, Object> params = new HashMap<>();
params.put("page", 0); // 第 0 页
params.put("size", 15); // 每页 15 条
params.put("age", 20); // 年龄参数为 20
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
5
使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field(User::getAge, 20) // 年龄参数为 20
.page(0, 15) // 第 0 页, 每页 15 条
.build();
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
5
分页查询年龄大于 20 的用户列表:
Map<String, Object> params = new HashMap<>();
params.put("page", 0); // 第 0 页
params.put("size", 15); // 每页 15 条
params.put("age", 20); // 年龄参数为 20
params.put("age-op", GreaterThan.class); // 年龄字段运算符为:大于
SearchResult<User> res = searcher.search(User.class, params);
2
3
4
5
6
使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field(User::getAge, 20).op(GreaterThan.class) // 年龄参数为 20, 运算符为:GreaterThan
.page(0, 15) // 第 0 页, 每页 15 条
.build();
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
5
分页查询年龄在 20 与 30 之间用户列表:
Map<String, Object> params = new HashMap<>();
params.put("page", 0); // 第 0 页
params.put("size", 15); // 每页 15 条
params.put("age-0", 20); // 年龄第 0 个参数为 20
params.put("age-1", 30); // 年龄第 1 个参数为 30
params.put("age-op", Between.class); // 年龄字段运算符为:Between
SearchResult<User> res = searcher.search(User.class, params);
2
3
4
5
6
7
使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field(User::getAge, 20, 30).op(Between.class) // 年龄参数为 20 和 30, 运算符为:Between
.page(0, 15) // 第 0 页, 每页 15 条
.build();
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
5
分页查询年龄为 18, 20, 25 的用户列表:
Map<String, Object> params = new HashMap<>();
params.put("page", 0); // 第 0 页
params.put("size", 15); // 每页 15 条
params.put("age-0", 18); // 年龄第 0 个参数为 18
params.put("age-1", 20); // 年龄第 1 个参数为 20
params.put("age-2", 25); // 年龄第 2 个参数为 25
params.put("age-op", MultiValue.class); // 年龄字段运算符为:多值查询
SearchResult<User> res = searcher.search(User.class, params);
2
3
4
5
6
7
8
使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field(User::getAge, 18, 20, 25).op(MultiValue.class) // 年龄参数为 18, 20, 25, 运算符为:MultiValue
.page(0, 15) // 第 0 页, 每页 15 条
.build();
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
5
分页查询姓张的用户:
Map<String, Object> params = new HashMap<>();
params.put("page", 0); // 第 0 页
params.put("size", 15); // 每页 15 条
params.put("name", "张"); // 姓名参数为 张
params.put("name-op", StartWith.class); // 姓名字段运算符为:以...开头
SearchResult<User> res = searcher.search(User.class, params);
2
3
4
5
6
使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.field(User::getName, "张").op(StartWith.class) // 姓名参数为 张, 运算符为:StartWith
.page(0, 15) // 第 0 页, 每页 15 条
.build();
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
5
分页查询并按年龄排序:
Map<String, Object> params = new HashMap<>();
params.put("page", 0); // 第 0 页
params.put("size", 15); // 每页 15 条
params.put("sort", "age"); // 排序字段:年龄
params.put("order", "asc"); // 排序方法:升序 asc, 降序 desc
SearchResult<User> res = searcher.search(User.class, params);
2
3
4
5
6
使用参数构建器的等效写法(since v2.2.0):
Map<String, Object> params = MapUtils.builder()
.orderBy(User::getAge, "asc") // 按年龄排序,升序
.page(0, 15) // 第 0 页, 每页 15 条
.build();
SearchResult<User> result = searcher.search(User.class, params);
2
3
4
5
SQL 日志
如果需要查看 Bean Searcher 的 SQL 执行日志,只需在您的日志配置文件中将 com.ejlchina.searcher.implement.MainSearchSqlExecutor
的日志级别调整为 DEBUG
即可。在 SpringBoot 项目中,可参考 logback-spring.xml 文件。
输出级别配置好后,SQL 日志的效果如下: