條件查詢
抽象類Wrapper是所有條件構造器的父類,我們使用它的子類QueryWrapper完成條件構造。
QueryWrapper封裝的方法
setSqlSelect 設置 SELECT 查詢字段
where WHERE 語句,拼接 + WHERE 條件
and AND 語句,拼接 + AND 字段=值
andNew AND 語句,拼接 + AND (字段=值)
or OR 語句,拼接 + OR 字段=值
orNew OR 語句,拼接 + OR (字段=值)
eq 等於=
allEq 基於 map 內容等於=
ne 不等於<>
gt 大於>
ge 大於等於>=
lt 小於<
le 小於等於<=
like 模糊查詢 LIKE
notLike 模糊查詢 NOT LIKE
in IN 查詢
notIn NOT IN 查詢
isNull NULL 值查詢
isNotNull IS NOT NULL
groupBy 分組 GROUP BY
having HAVING 關鍵詞
orderBy 排序 ORDER BY
orderAsc ASC 排序 ORDER BY
orderDesc DESC 排序 ORDER BY
exists EXISTS 條件語句
notExists NOT EXISTS 條件語句
between BETWEEN 條件語句
notBetween NOT BETWEEN 條件語句
addFilter 自由拼接 SQL
last 拼接在最后,例如:last("LIMIT 1")
如果點進每一個方法查看源碼發現,所有方法都調用了一個同名的方法,這個方法的第一個參數為 boolean condition,它表示該條件是否加入最后生成的sql中,如果設為false,則沒有改條件。使用場景:多條件查詢時,根據是否傳遞該屬性值來決定SQL生成。
//like的源碼
default Children like(R column, Object val) {
return this.like(true, column, val);
}
查詢全部字段
查詢用戶名中有 “m”的數據
@Test
public void selectCondition1() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("user_name", "m");
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
查詢姓名有“m”,年齡在0-20歲之間,上級id不為null的數據
@Test
public void selectCondition2() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("user_name", "m").between("age", 0, 20).isNotNull("manager_id");
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
姓氏為"m",或者年齡大於7歲,按照年齡降序排序,年齡相同的按照id升序
@Test
public void selectCondition3() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
/*
* like: '%值%'
* likeLeft: '%值'
* lifeRight: '值%'
*/
queryWrapper.likeRight("user_name", "m").or().ge("age", 7)
.orderBy(true, false, "age")
.orderBy(true, true, "id");
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
查詢姓氏為"m",並且年齡小於40且大於3
@Test
public void selectCondition4() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("user_name", "m").and(qw -> qw.lt("age", 30).gt("age", 3));
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
查詢部分字段
只需要id,name字段
@Test
public void selectCondition5() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("id", "user_name").like("user_name", "m").lt("age", 30);
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
排除email,age字段
@Test
public void selectCondition6() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select(User.class, user -> !user.getColumn().equals("age") && !user.getColumn().equals("email"));
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
對象實例作構造方法參數
上面使用的條件構造器中,采用的都是無參構造方法,MP允許我們傳遞實體對象給條件構造器,其中實體對象不為null的屬性將作為where條件,默認 = 比較。實例生成的where條件與各個Api生成的where條件沒有任何關聯行為,都會出現在sql的where中。
@Test
public void selectCondition7() {
User user = new User();
user.setName("mike");
user.setAge(10)
QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/*
未使用其他方法:
生成Sql: where user_name = ? AND age = ?
加上條件queryWrapper.likeRight("user_name","m").gt("age",10);
生成Sql:where user_name = ? AND age = ? AND (user_name LIKE ? AND age > ?)
*/
傳入對象實例默認構造的where條件是 等值 = 比較,某些場景下不符合我們的要求,此時可以使用之前提到過的@TableFiled注解,在name上標注@TableFiled(condition = SqlCondition.LIKE),來改變默認條件。改變默認條件后,生成的SQL:WHERE user_name LIKE CONCAT('%' , ? , %") AND age = ?
/**
* SQL 比較條件常量定義類
*/
public class SqlCondition {
/**
* 等於
*/
public static final String EQUAL = "%s=#{%s}";
/**
* 不等於
*/
public static final String NOT_EQUAL = "%s<>#{%s}";
/**
* % 兩邊 %
*/
public static final String LIKE = "%s LIKE CONCAT('%%',#{%s},'%%')";
/**
* % 左
*/
public static final String LIKE_LEFT = "%s LIKE CONCAT('%%',#{%s})";
/**
* 右 %
*/
public static final String LIKE_RIGHT = "%s LIKE CONCAT(#{%s},'%%')";
}
這里還可以自定義構造條件,不同場景不同方式,不再贅述。
更多查詢方法
SelectMaps
@Test
public void selectCondition8() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
List<Map<String, Object>> users = userMapper.selectMaps(queryWrapper);
System.out.println(users);
}
使用SelectMaps看似跟SelectList沒有區別,看一下打印結果:
[{create_time=2021-07-20T17:13:31, manager_id=2, name=mike, id=1, age=10, email=mikemike@qq.com},
{create_time=2021-07-20T17:41:14, name=tom, id=2, age=24, email=tomtom@qq.com},
{create_time=2021-07-19T14:15:50, manager_id=1, name=ez, id=3, age=20, email=ezez@qq.com}]
SelectMaps幫我們剔去了值為null的字段,當大量字段是null時,為了方便看數據,SelectMaps就出場了。
@Test
public void selectCondition8() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("id","user_name","email");
List<Map<String, Object>> users = userMapper.selectMaps(queryWrapper);
System.out.println(users);
}
打印結果:
[{user_name=mike, id=1, email=mikemike@qq.com}, {user_name=tom, id=2, email=tomtom@qq.com}, {user_name=ez, id=3, email=ezez@qq.com}]
SelectObjs
根據Wrapper條件,查詢全部記錄,但只返回第一個字段的值。
@Test
public void selectCondition9() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
List<Object> objects = userMapper.selectObjs(queryWrapper);
System.out.println(objects);
}
第一個字段是id,所以打印結果:[1, 2, 3]
SelectCount
根據QuerWrapper條件查詢總數
@Test
public void selectCondition10() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age",10);
Integer count = userMapper.selectCount(queryWrapper);
System.out.println(count);
}
/**
* 使用selectCount方法不能知道查詢的列名
* 生成SQL:SELECT COUNT( 1 ) FROM user WHERE (age >= ?)
*/
打印結果:3 (有3條年齡大於等於10的數據)
SelectOne
根據queryWrapper條件返回一條記錄,且只能返回一條或Null,否則報錯。
@Test
public void selectCondition11() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "mike");
User user = userMapper.selectOne(queryWrapper);
System.out.println(user);
}
打印結果:
User(id=1, name=mike, age=10, email=mikemike@qq.com, managerId=2, createTime=2021-07-20T17:13:31, updateTime=null, version=null, deleteId=null)
lambda條件構造器
除了上面的QueryWrapper
條件構造器,MP還提供了Lambda條件構造器,它能防止我們寫錯字段名稱。
三種方式創建Lambda條件構造器:
LambdaQueryWrapper<User> lambdaWrapper = new QueryWrapper<User>().lambda();
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
LambdaQueryWrapper<User> lambdaWrapper = Wrappers.lambdaQuery();
測試:
@Test
public void lamdaTest() {
LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.like(User::getName, "tom").ge(User::getAge, 10);
List<User> userList = userMapper.selectList(lambdaQueryWrapper);
userList.forEach(System.out::println);
}
打印結果:
User(id=2, name=tom, age=24, email=tomtom@qq.com, managerId=null, createTime=2021-07-20T17:41:14, updateTime=null, version=null, deleteId=null)
LambdaQueryChainWrapper
允許我們鏈式構造where條件和調用查詢方法。
@Test
public void lambdaTest2() {
List<User> userList = new LambdaQueryChainWrapper<User>(userMapper)
.like(User::getName, "mike")
.ge(User::getAge, 10).list();
userList.forEach(System.out::println);
}
打印結果:
User(id=1, name=mike, age=10, email=mikemike@qq.com, managerId=2, createTime=2021-07-20T17:13:31, updateTime=null, version=null, deleteId=null)
查看LambdaQueryChainWrapper源碼,實際上內部新創建了LambdaQueryWrapper,和分開寫條件並沒什么區別。
LambdaQueryChainWrapper 實現了ChainQuery