接口 io.mybatis.mapper.example.ExampleMapper<T, E>
Example 类相关的查询方法,Example 中扩展了一些新的方法,因此默认的 Example 查询已经不支持 MBG 生成的 XXExample 对象作为参数。
Example的用法请参考: mapper4 example useage doc (opens new window), 注意:这里的example和mapper4的用法也不完全一样,详细用法请参考example 单元测试 (opens new window)
先看接口中包含的方法:
default Example<T> example()
: 返回Example<T>
对象,自己也可以直接 newint deleteByExample(E example)
: 根据Example
删除int updateByExample(@Param("entity") T entity, @Param("example") E example)
: 根据Example
条件批量更新实体信息int updateByExampleSelective(@Param("entity") T entity, @Param("example") E example);
: 根据Example
条件批量更新实体不为空的字段List<T> selectByExample(E example)
: 根据Example
条件批量查询Optional<T> selectOneByExample(E example)
: 根据Example
条件查询单个实体int countByExample(E example)
: 根据Example
条件查询总数
接口源码中还注释了几个方法,这些方式是用来说明 2.1.3 使用 Java8 默认方法灵活实现通用方法 的特点,这里不重复介绍。
看完接口方法,在看看 Example
对象中增加了那些特殊的字段和方法:
public class Example<T> {
/**
* 排序字段
*/
protected String orderByClause;
/**
* 是否使用 distinct
*/
protected boolean distinct;
/**
* 指定查询列
*/
protected String selectColumns;
/**
* 起始 SQL,添加到 SQL 前,注意防止 SQL 注入
*/
protected String startSql;
/**
* 结尾 SQL,添加到 SQL 最后,注意防止 SQL 注入
*/
protected String endSql;
/**
* 多组条件通过 OR 连接
*/
protected List<Criteria<T>> oredCriteria;
/**
* 允许Example查询条件为空
*/
protected boolean allowCriteriaEmpty;
//省略其他
}
# 2.3.1 orderByClause
排序字段是默认就有的,但是为了字段使用的安全,增加了额外的赋值方法:
/**
* 通过方法引用方式设置排序字段
*
* @param fn 排序列的方法引用
* @param order 排序方式
* @return Example
*/
public Example<T> orderBy(Fn<T, Object> fn, Order order) {
if (orderByClause == null) {
orderByClause = "";
}
orderByClause += fn.toColumn() + " " + order;
return this;
}
示例:
example.orderBy(User::getId, Example.Order.DESC);
这会生成 ORDER BY id desc
排序。
# 2.3.2 distinct
去重 distinct 也是默认的。如果设置为 true
,查询时就会使用 SELECT DISTINCT ...
。
# 2.3.3 selectColumns
selectColumns
是新增的,可以用来指定查询列,对应的方法如下:
/**
* 指定查询列
*
* @param fns 方法引用
*/
public Example<T> selectColumns(Fn<T, Object>... fns) {
if (selectColumns == null) {
selectColumns = "";
}
for (Fn<T, Object> fn : fns) {
String column = fn.toColumn();
String field = fn.toField();
if (selectColumns.length() != 0) {
selectColumns += ",";
}
if (column.equals(field)) {
selectColumns += column;
} else {
selectColumns += column + " AS " + field;
}
}
return this;
}
用法示例:
<User> example = exampleMapper.example();
example.selectColumns(User::getUserName, User::getSex);
//可以多次调用追加查询列
example.selectColumns(User::getId);
指定查询列后,在 SQL 中会变成 select name as userName, sex, id from ...
(userName
映射的 name
)。
# 2.3.4 startSql
新增加的字段,起始 SQL,添加到 SQL 前,注意防止 SQL 注入。
直接通过 set 方法设置值:
/**
* 设置起始 SQL
*
* @param startSql 起始 SQL,添加到 SQL 前,注意防止 SQL 注入
*/
public void setStartSql(String startSql) {
this.startSql = startSql;
}
这个字段基本上要配合下面的 endSql
字段一起用,下面示例:
example.setStartSql("select * from (");
example.setEndSql(") tmp limit 1");
示例没太大意义,你可以想个更好的例子来更新此处文档。
# 2.3.5 endSql
和上面新增加的字段类似:结尾 SQL,添加到 SQL 最后,注意防止 SQL 注入
也是直接通过 set 方法设置:
/**
* 设置结尾 SQL
*
* @param endSql 结尾 SQL,添加到 SQL 最后,注意防止 SQL 注入
*/
public void setEndSql(String endSql) {
this.endSql = endSql;
}
示例看前一个字段的。
# 2.3.6 oredCriteria
默认就有的字段,记录查询条件块。
# 2.3.7 allowCriteriaEmpty
这个字段是新增的,这个字段破坏了 Example 的整体结构,主要目的是在使用时决定:是否允许查询条件为空
当 select 查询时,是可以为空的,这种情况就是查询了全表,由于这个字段默认值为 false
不允许,因此你需要 new Example(true)
才行。
当 delete, update 时,默认不允许为空,这可以避免清库和更新全库。这个参数只在下面方法用到:
/**
* 获取所有条件,当前方法会校验所有查询条件,如果不存在查询条件就抛出异常。
* <p>
* 不允许通过 Example 相关方法操作全表!!!
*
* @return 条件
*/
public List<Criteria<T>> getOredCriteria() {
if (!allowCriteriaEmpty) {
if (oredCriteria.size() == 0) {
throw new IllegalArgumentException("Example 条件不能为空");
}
boolean noCriteria = true;
for (Criteria<T> criteria : oredCriteria) {
if (!criteria.getCriteria().isEmpty()) {
noCriteria = false;
break;
}
}
if (noCriteria) {
throw new IllegalArgumentException("Example 条件不能为空");
}
}
return oredCriteria;
}
当获取查询条件时判断,如果没有有效的查询条件,就抛出异常,避免潜在的风险。
# 2.3.8 clear()
方法
最后说一个方法,同一个 Example
对象经过 clear()
后是可以反复使用的:
/**
* 清除所有设置
*/
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
selectColumns = null;
startSql = null;
endSql = null;
allowCriteriaEmpty = false;
}
特别注意的是 allowCriteriaEmpty
,即使你用 Example(true)
创建的,这里也会设置为 false
,想要设置 true
可以调用下面方法:
/**
* 设置是否允许查询条件为空
*
* @param allowCriteriaEmpty true允许空,一般用于查询,false不允许空,一般用于修改和删除
*/
public void allowCriteriaEmpty(boolean allowCriteriaEmpty) {
this.allowCriteriaEmpty = allowCriteriaEmpty;
}
# 2.3.9 简单示例
介绍完所有字段和一个特殊方法,下面看几个 Example
示例:
Example<User> example = new Example();
example.createCriteria().andGreaterThan(User::getId, 10L).andLike(User::getUserName, "殷%");
Assert.assertEquals(3, exampleMapper.deleteByExample(example));
example.clear();
example.createCriteria().andEqualTo(User::getId, 1L);
User user = new User();
user.setId(1L);
user.setUserName("男主角");
Assert.assertEquals(1, exampleMapper.updateByExample(user, example));
剩下的,你需要掌握的就是 andGreaterThan
和 andEqualTo
这类的方法,这些方法通过名字可以直接理解。