Mybatis -plus -jion的复习

news2025/3/1 11:14:52

Mybatis -plus -jion

是一个 MyBatis-Plus 的增强工具,在 MyBatis-Plus 的基础上只做增强不做改变,为简化开发、提高效率而生。

- **无侵入**:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- **损耗小**:启动即会自动注入基本 JOIN,性能基本无损耗,直接面向对象操作
- **支持 Lambda 形式调用**:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- **无学习成本**:支持MP风格的查询, 您会MP就会MPJ, 无需额外的学习成本
- **完美适配**:兼容MP的别名、逻辑删除、枚举列、TypeHandle列等特性
- **注解支持**:支持注解形式一对一、一对多和连表查询形式的一对一和一对多

继承与BaseMapper接口,所以可以使用 BaseMapper的方法。

1、jion的依赖和与配置文件

1.依赖:

<dependency>
  <groupId>com.github.yulichang</groupId>
  <artifactId>mybatis-plus-join-boot-starter</artifactId>
  <version>1.5.2</version>
</dependency>

2.让Dao层实现MPJBaseMapperch接口 、Service实现、实现类impl 类实现接口

@Mapper
public interface UserMapper extends MPJBaseMapper<User> {

}
  
public interface UserService extends MPJBaseService<User> {

}
  
@Service
public class UserServiceImpl extends MPJBaseServiceImpl<UserMapper, User> implements UserService {

}  

3.配置文件

mybatis-plus-join:
#是否打印 mybatis plus join banner 默认true
banner: true
#全局启用副表逻辑删除(默认true) 关闭后关联查询不会加副表逻辑删除
sub-table-logic: true
#拦截器MappedStatement缓存(默认true)
ms-cache: true
#表别名(默认 t)
table-alias: t
#副表逻辑删除条件的位置,支持where、on
#默认ON (1.4.7.2及之前版本默认为where)
logic-del-type: on

4.额外的注解映射


@Data
@TableName("user")
public class User {

    @TableId
    private Integer id;
    private Integer pid;//父id
    /* 其他属性略 */

    /**
     * 查询上级 一对一
     */
    @TableField(exist = false)
    @EntityMapping(thisField = "pid", joinField = "id")
    private User parentUser;

    /**
     * 查询下级 一对多
     */
    @TableField(exist = false)
    @EntityMapping(thisField = "id", joinField = "pid")
    private List<User> childUser;

    /**
     * 带条件的查询下级 一对多
     */
    @TableField(exist = false)
    @EntityMapping(thisField = "id", joinField = "pid",
                   condition = {
                       //sex = '0' 默认条件是等于
                       @Condition(column = "sex", value = "0"),
                       //name like '%a%'
                       @Condition(column = "name", value = "张三", keyWord = SqlKeyword.LIKE)
                   },
                   apply = @Apply(value = "id between 1 and 20"))//拼接sql 同 wrapper.apply()
    private List<User> childUserCondition;

    /**
     * 查询地址 (一对多)
     */
    @TableField(exist = false)
    @EntityMapping(thisField = "id", joinField = "userId")
    private List<Address> addressList;

    /**
     * 绑定字段 (一对多)
     */
    @TableField(exist = false)
    @FieldMapping(tag = User.class, thisField = "id", joinField = "pid", select = "id")
    private List<Integer> childIds;
}

2、MPJBaseMapper 接口的 中的方法的使用

 代码结构使用注意:
MPJLambdaWrapper<主表> wrapper = new MPJLambdaWrapper<主表.class>()
        .leftJoin(从表.class, 从表::getUserId, 主表::getId)
        .eq(主表::getId, 2);
Integer count = userMapper.selectJoinCount(对应需要封装的实体.class,wrapper);
System.out.println(count);

1.selectJoinCount()联表查询总的条数

MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>()
        .leftJoin(Address.class, Address::getUserId, User::getId)
        .eq(User::getId, 2);
Integer count = userMapper.selectJoinCount(wrapper);
System.out.println(count);
1. 对应的sql语句
SELECT COUNT(*)
FROM user t
         LEFT JOIN address t1 ON (t1.user_id = t.id)
WHERE (t.id = ?)

2.selectJoinOne() 联表查询一条记录

 MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>()
                .selectAll(User.class)
                .select(Address::getAddress)
                .leftJoin(Address.class, Address::getUserId,User::getId)
                .eq(User::getId, 2);
// DTO 自己封装的包含两个实体类字段的 类
        UserDTO dto = userMapper.selectJoinOne(UserDTO.class, wrapper);
1. 对应的sql语句
SELECT 
    t.id,
    t.name,
    t.sex,
    t.head_img,
    t1.address 
FROM 
    user t 
    LEFT JOIN address t1 ON t1.user_id = t.id 
WHERE (
    t.id = 2)

3.selectJoinList() 查询复合条件的所有记录

MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>()
                .selectAll(User.class)
                .select(Address::getTel)
                .leftJoin(Address.class, Address::getUserId, User::getId)
                .eq(User::getId, 2);
 List<UserDTO> list = userMapper.selectJoinList(UserDTO.class, wrapper);
    }
1. 对应的sql语句
SELECT t.id,
       t.name,
       t.sex,
       t.head_img,
       t1.tel
FROM user t
         LEFT JOIN address t1 ON t1.user_id = t.id
WHERE (t.id = 2)    

4.selectJoinPage(new Page<>(1, 10), UserDTO.class, wrapper) jion的分页查询

1. new Page<>(1, 10):分一页,10条数据。
 MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>()
                .selectAll(User.class)
                .select(Address::getAddress)
                .leftJoin(Address.class, Address::getUserId, User::getId)
                .eq(User::getId, 1);
        IPage<UserDTO> page = userMapper.selectJoinPage(new Page<>(1, 10), UserDTO.class, wrapper);
2. 对应的sql语句

5.selectJoinMap() 联表查询一条记录,返回Map集合 类似selectJoinOne()

 MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>()
                .selectAll(User.class)
                .select(Address::getAddress)
                .leftJoin(Address.class, Address::getUserId,User::getId)
                .eq(User::getId, 2);
// DTO 自己封装的包含两个实体类字段的 类
        Map<UserDTO> dtoMap = userMapper.selectJoinMap(UserDTO.class, wrapper);
1. 对应的sql语句
SELECT 
    t.id,
    t.name,
    t.sex,
    t.head_img,
    t1.address 
FROM 
    user t 
    LEFT JOIN address t1 ON t1.user_id = t.id 
WHERE (
    t.id = 2)

6.selectJoinMaps () 连表查询所有命中记录,返回List集合

public List<Map<String, Object>> getUserWithRoleInfo() {
        // 使用lambda表达式构建关联查询条件
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        // 进行内联查询,关联role表,关联条件是user表的roleId等于role表的id
        return userMapper.selectJoinMaps(queryWrapper, User.class, "role",
                user -> user.getRoleId().equals(joiner.table("role").get("id")));

7.selectJoinMapsPage() 连表分页查询返回命中记录,返回List集合

 public Page<Map<String, Object>> getUserWithRoleInfoPageByRoleName(int currentPage, int pageSize, String roleName) {
        Page<User> page = new Page<>(currentPage, pageSize);
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();

        // 添加筛选条件,通过子查询找到符合角色名的role表中的id,再匹配user表中的roleId
        queryWrapper.inSql(User::getRoleId, "select id from role where role_name = '" + roleName + "'");

        return userMapper.selectJoinMapsPage(page, queryWrapper, User.class, "role",
                user -> user.getRoleId().equals(joiner.table("role").get("id")));
    }

8.deleteJoin 联表删除,支持逻辑删除

// yml文件配置开启逻辑删除
mybatis-plus-join:
  #关闭副表逻辑删除 默认开启(true)
  sub-table-logic: false

9.deleteJion() 联表删除符合的主表的记录,返回 int 条数

DeleteJoinWrapper<User> wrapper = JoinWrappers.delete(User.class)
                .leftJoin(Address.class, Address::getUserId, User::getId)
                .leftJoin(Area.class, Area::getId, Address::getAreaId)
                .eq(User::getId, 1);
                //删除主表User的记录
        int i = userMapper.deleteJoin(wrapper);
1. 对应的sql语句
==>  Preparing: DELETE t FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) LEFT JOIN area t2 ON (t2.id = t1.area_id) WHERE (t.id = 1)
==> Parameters: 1(Integer)
<==    Updates: 1

10.deleteAll() 联表删除表全部的记录.

  DeleteJoinWrapper<User> wrapper = JoinWrappers.delete(User.class)
                //删除全部的表数据 (主表和副表)
                .deleteAll()
                //也可以删除指定的表数据,调用 delete() 传要删除的实体类class 如下
                //.delete(User.class, Address.class, Area.class)
                .leftJoin(Address.class, Address::getUserId, User::getId)
                .leftJoin(Area.class, Area::getId, Address::getAreaId)
                .eq(User::getId, 1);
        int i = userMapper.deleteJoin(wrapper);
1. 对应的sql语句
==>  Preparing: DELETE t,t1,t2 FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id) LEFT JOIN area t2 ON (t2.id = t1.area_id) WHERE (t.id = ?)
==> Parameters: 1(Integer)
<==    Updates: 19

11.update 联表修改表记录

12.updateJion()、wrapper设置set语句和where条

 UpdateJoinWrapper<User> update = JoinWrappers.update(User.class)
                .set(User::getName, "aaaaaa")
                .set(Address::getAddress, "bbbbb")
                .leftJoin(Address.class, Address::getUserId, User::getId)
                .eq(User::getId, 1);
        int i = userMapper.updateJoin(null, update);
1. 对应的sql语句
UPDATE
    `user` t
    LEFT JOIN address t1
ON (t1.user_id = t.id)
    SET t.`name`=?, t1.address=?
WHERE (t.id = ?)

13.updateJoinAndNull () 联表更新,更新字段可以为null

UpdateJoinWrapper<User> update = JoinWrappers.update(User.class)
                .set(User::getName, "aaaaaa")
                .set(Address::getAddress, "bbbbb")
                .leftJoin(Address.class, Address::getUserId, User::getId)
                .eq(User::getId, 1);
        int i = userMapper.updateJoinAndNull(null, update);
1. 对应的sql语句
UPDATE
    `user` t
    LEFT JOIN address t1
ON (t1.user_id = t.id)
    SET t.`name`=?, t1.address=?
WHERE (t.id = ?)

3、MPJlambadaWarpper 的方法的使用

1.distinct 去重

wrapper.distinct()

2.select 查询指定字段

//单个字段
select(User::getId)
//多个字段
select(User::getId,User::getSex,User::getName) 

3.selectFilter() 过滤字段

//只要 java 字段名以 "test" 开头的
selectFilter(User.class, i -> i.getColumProperty().startsWith("test"))
// 只要 数据库 字段名以 "test" 开头的
.selectFilter(User.class, i -> i.getColumn().startsWith("test"))
// 只要 java 字段类型是String的
.selectFilter(User.class, e -> e.getColumnType() == String.class)

4.selectAll() 去重 查询类的全部字段

// 查询指定类的全部字段
wrapper.selectAll(User.class)
// 查询User类的全部字段,除了name,支持可变参数          
wrapper.selectAll(User.class, User::getName)

5.selectAsClass 查询两个类的交集字段

// t.name AS nickname
wrapper.selectAsClass("t.name", UserDTO::getNickname))

6.selectFunc sql函数

// 支持定义别名
selectSum(User::getId) -> SUM(t.id) AS id
selectCount(User::getId) -> COUNT(t.id) AS id
selectMax(User::getId) -> MAX(t.id) AS id
selectMin(User::getId) -> MIN(t.id) AS id
selectAvg(User::getId) -> AVG(t.id) AS id
selectLen(User::getId) -> LEN(t.id) AS id

7.selectCollection 一对多查询,类中存在其他类的集合

1. 将Address类的字段全部映射到UserDTO类的 addressLis集合中
.selectCollection(Address.class, UserDTO::getAddressList)
2. <font style="color:#ECAA04;">指定实体字段映射</font>(只映射 id 和 address 两个字段) id、result方法对应mybatis中ResultMap里的 `<id>` 和 `<result>` 标签
.selectCollection(Address.class, UserDTO::getAddressList, map -> map
        //此处只能映射 Address.class 中的字段到 UserDTO::getAddressList 中
        .id(Address::getId)
        .result(Address::getAddress)
        //别名映射
        .result(Address::getAddress, AddressDTO::getAddress));
3. 字段映射,把address表中的id映射到UserDTO的 `List<String>` 属性的addressIds字段中
.selectCollection(Address.class, UserDTO::getAddressIds, map -> map
                    .result(Address::getId))
4. 不指定实体字段映射(只映射 id 和 address 两个字段) id、result方法对应mybatis中ResultMap里的 `<id>` 和 `<result>` 标签
.selectCollection(UserDTO::getAddressList, map -> map
        //可以映射不同类的字段 到 UserDTO::getAddressList 中 比如 Address 和 User
        .id(Address::getId)
        .result(User::getName, AddressDTO::getAddress)
        //别名映射
        .result(User::getAddr, AddressDTO::getAddress));

8.selectAssociation 一对一查询

// 支持定义别名
selectSum(User::getId) -> SUM(t.id) AS id
selectCount(User::getId) -> COUNT(t.id) AS id
selectMax(User::getId) -> MAX(t.id) AS id
selectMin(User::getId) -> MIN(t.id) AS id
selectAvg(User::getId) -> AVG(t.id) AS id
selectLen(User::getId) -> LEN(t.id) AS id

9.selectSub 子查询

MPJLambdaWrapper<User> wrapper = JoinWrappers.lambda(User.class)
                .selectSub(User.class, w -> w.select(User::getId)
                        .eq(User::getId, User::getId)
                        .last("limit 1"), User::getId)
                .leftJoin(Address.class, Address::getUserId, User::getId)
                .le(User::getId, 100);
        wrapper.list();
1. 对应的字段
SELECT 
    (SELECT st.id FROM `user` st WHERE (st.id = t.id) limit 1 ) AS id
FROM `user` t LEFT JOIN address t1
ON (t1.user_id = t.id)
WHERE t1.del= false AND (t.id <= ?)

10.selectFunc sql函数

// 支持定义别名
selectSum(User::getId) -> SUM(t.id) AS id
selectCount(User::getId) -> COUNT(t.id) AS id
selectMax(User::getId) -> MAX(t.id) AS id
selectMin(User::getId) -> MIN(t.id) AS id
selectAvg(User::getId) -> AVG(t.id) AS id
selectLen(User::getId) -> LEN(t.id) AS id

4、union/union all 联合查询

1.实例

 MPJLambdaWrapper<User> w = JoinWrappers.lambda(User.class)
                .selectAll(User.class)
                .union(User.class, union -> union
                        .selectAll(User.class))
                .union(User.class, union -> union
                        .selectAll(User.class));
        //union all 调用unionAll即可 如下
        //.unionAll(User.class, union -> union...);
        w.list();
1. 对应的sql
SELECT t.id,
       t.pid,
       t.`name`,
       t.`json`,
       t.sex,
       t.head_img,
       t.create_time
FROM `user` t
UNION
SELECT t.id,
       t.pid,
       t.`name`,
       t.`json`,
       t.sex,
       t.head_img,
       t.create_time
FROM `user` t
UNION
SELECT t.id,
       t.pid,
       t.`name`,
       t.`json`,
       t.sex,
       t.head_img,
       t.create_time
FROM `user` t

5、条件构造器

无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。

所有的 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 都继承自 AbstractWrapper。

1.allEq 方法是 MyBatis-Plus 中用于构建查询条件的方法之一,它允许我们通过一个 Map 来设置多个字段的相等条件。

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.allEq(Map.of("id", 1, "name", "老王", "age", null));
-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE id = 1 AND name = '老王' AND age IS NULL

2.eq()方法是 它允许我们通过一个字段的相等条件。ne()反之

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getName, "老王");
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "老王");

3.gt()方法是 ,它允许我们设置单个字段大于条件。ge() 大于等于 it() 小于 le() 小于等于

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.allEq(Map.of("id", 1, "name", "老王", "age", null));
-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE id = 1 AND name = '老王' AND age IS NULL

4.beetween() 设置一个字段的between条件。notbeetween()反之

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.between("age", 18, 30);
-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE age BETWEEN 18 AND 30

5.like() 设置一个字段的模糊查询。notlike()反之

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "王");
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.like(User::getName, "王");

6.likeLeft() 设置一个字段的左模糊条件。likeRight()反之

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeLeft("name", "王");
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.likeLeft(User::getName, "王");

7.isNull() 设置单个字段的 非空 条件

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.isNull("name");

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.isNull(User::getName);

8.in() 设置一个字段的 IN 条件。notIn()反之

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.notIn("age", Arrays.asList(1, 2, 3));

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.notIn(User::getAge, Arrays.asList(1, 2, 3));

9.inSql() 设置一个字段的 IN 条件、可以写sql语句 notInSql()反之

QQueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("age", "1,2,3,4,5,6");
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.inSql(User::getAge, "1,2,3,4,5,6");
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("id", "select id from other_table where id < 3");

10.eqSql() 你设置一个字段=某个 SQL 语句的结果。这个方法特别适用于需要将字段值与子查询结果进行比较的场景。

11.gtSql() :>某个sql、geSql():>=某个sql、ltSql()<某个sql、leSql()<=某个sql

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.geSql("id", "select id from table where name = 'xx'");

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.geSql(User::getId, "select id from table where name = 'xx'");

对应的sql

-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE id >= (select id from table where name = 'xx')

12.groupBy() 设置字段的分组条件。having:条件

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.groupBy("age").having("sum(age) > 10");

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.groupBy(User::getAge).having("sum(age) > {0}", 10);

13.orderByAsc() 查询结果的升序排序条件。通过指定一个或多个字段,orderByDesc() 反之

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("id", "name");

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderByAsc(User::getId, User::getName);

14.orderBy() 设置一个字段的排序方法。true:Asc false:Desc

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderBy(true, true, "id", "name");

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderBy(true, true, User::getId, User::getName);

15.func() 提供了一种在链式调用中根据条件执行不同查询操作的机制。通过传入一个 Consumer 函数式接口,func 方法允许你在不中断链式调用的情况下,根据条件执行不同的查询构建逻辑。

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.func(i -> {
    if (true) {
        i.eq("id", 1);
    } else {
        i.ne("id", 1);
    }
});
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.func(i -> {
    if (true) {
        i.eq(User::getId, 1);
    } else {
        i.ne(User::getId, 1);
    }
});
-- 根据条件生成的 SQL 会有所不同
-- 如果条件为 true,则生成的 SQL 为:
SELECT * FROM user WHERE id = 1

-- 如果条件为 false,则生成的 SQL 为:
SELECT * FROM user WHERE id != 1

16.or() 通过调用 or 方法,可以改变后续查询条件的连接方式,从默认的 AND 连接变为 OR 连接。

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", 1).or().eq("name", "老王");
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getId, 1).or().eq(User::getName, "老王");
-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE id = 1 OR name = '老王'

17.and() 在查询条件中添加 AND 逻辑。通过调用 and 方法,可以创建 AND 嵌套条件,即在一个 AND 逻辑块中包含多个查询条件。

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.and(i -> i.and(j -> j.eq("name", "李白").eq("status", "alive"))
                         .and(j -> j.eq("name", "杜甫").eq("status", "alive")));

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.and(i -> i.and(j -> j.eq(User::getName, "李白").eq(User::getStatus, "alive"))
                              .and(j -> j.eq(User::getName, "杜甫").eq(User::getStatus, "alive")));
-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE ((name = '李白' AND status = 'alive') AND (name = '杜甫' AND status = 'alive'))

18.nested() 创建一个独立的查询条件块,不带默认的 AND 或 OR 逻辑。通过调用 nested 方法,可以在查询条件中添加一个嵌套的子句,该子句可以包含多个查询条件,并且可以被外部查询条件通过 AND 或 OR 连接。

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.nested(i -> i.eq("name", "李白").ne("status", "活着"));

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.nested(i -> i.eq(User::getName, "李白").ne(User::getStatus, "活着"));
-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE (name = '李白' AND status <> '活着')

19.apply() 直接拼接 SQL 片段到查询条件中。这个方法特别适用于需要使用数据库函数或其他复杂 SQL 构造的场景。

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.apply("id = 1");

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.apply("date_format(dateColumn, '%Y-%m-%d') = '2008-08-08'");
//使用参数占位符
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.apply("date_format(dateColumn, '%Y-%m-%d') = {0}", "2008-08-08");
-- 普通 Wrapper 生成的 SQL
SELECT * FROM user WHERE id = 1

-- Lambda Wrapper 生成的 SQL
SELECT * FROM user WHERE date_format(dateColumn, '%Y-%m-%d') = '2008-08-08'

-- 使用参数占位符生成的 SQL
SELECT * FROM user WHERE date_format(dateColumn, '%Y-%m-%d') = '2008-08-08'

20.last() 直接在查询的最后添加一个 SQL 片段,而不受 MyBatis-Plus 的查询优化规则影响。这个方法应该谨慎使用,因为它可能会绕过 MyBatis-Plus 的查询优化。

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.last("limit 1");

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.last("limit 1");
-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user LIMIT 1

21.exists() 在查询中添加一个 EXISTS 子查询。 notExists()反之

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.exists("select id from table where age = 1");

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.exists("select id from table where age = 1");
-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE EXISTS (select id from table where age = 1)

22.select() 指定在查询结果中包含哪些字段,predicate 可以过滤字段

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("id", "name", "age");

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.select(User::getId, User::getName, User::getAge);

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select(i -> i.getProperty().startsWith("test"));
-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT id, name, age FROM user

-- 使用 Predicate 过滤字段生成的 SQL
SELECT testField1, testField2 FROM user

23.set() 设置更新语句中的 SET 字段、可以设置为null

UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("name", "老李头");

LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.set(User::getName, "老李头");
-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
UPDATE user SET name = '老李头'

24.setSql() 允许你直接设置更新语句中的 SET 部分 SQL语句

setSql("name = '老李头'")
setSql("dateColumn={0}", LocalDate.now())
setSql("type={0,javaType=int,jdbcType=NUMERIC,typeHandler=xxx.xxx.MyTypeHandler}", "待处理字符串");

25.setIncrBy() 允许你指定一个字段,并使其在数据库中的值增加指定的数值。setDecrBy()反之

UpdateWrapper<Product> updateWrapper = new UpdateWrapper<>();
updateWrapper.setIncrBy(Product::getNum, 1);

LambdaUpdateWrapper<Product> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.setIncrBy(Product::getNum, 1);
L-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
UPDATE product SET num = num + 1

26.orderBy() 设置一个字段的排序方法。true:Asc false:Desc

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderBy(true, true, "id", "name");
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderBy(true, true, User::getId, User::getName);

27.orderBy() 设置一个字段的排序方法。true:Asc false:Desc

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderBy(true, true, "id", "name");
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderBy(true, true, User::getId, User::getName);

28.orderBy() 设置一个字段的排序方法。true:Asc false:Desc

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderBy(true, true, "id", "name");
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderBy(true, true, User::getId, User::getName);

6、自定义查询

1.使用@select()注解

public interface UserMapper extends BaseMapper<User> {
    @Select("SELECT * FROM user ${ew.customSqlSegment}")
    List<User> selectByCustomSql(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
}

要使用自定义 SQL,只需调用上述方法并传入一个 Wrapper 对象:

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "张三");

List<User> userList = userMapper.selectByCustomSql(queryWrapper);

2.使用xml 查询

List<MysqlData> getAll(Wrapper ew);
<select id="getAll" resultType="MysqlData">
    SELECT * FROM mysql_data ${ew.customSqlSegment}
</select>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2259581.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络-Wireshark探索ARP

使用工具 Wiresharkarp: To inspect and clear the cache used by the ARP protocol on your computer.curl(MacOS)ifconfig(MacOS or Linux): to inspect the state of your computer’s network interface.route/netstat: To inspect the routes used by your computer.Brows…

Qt之自定义动态调控是否显示日志

创作灵感 最近在芯驰x9hp上开发仪表应用。由于需要仪表警告音&#xff0c;所以在该平台上折腾并且调试仪表声音的时候&#xff0c;无意间发现使用&#xff1a; export QT_DEBUG_PLUGINS1 可以打印更详细的调试信息。于是想着自己开发的应用也可以这样搞&#xff0c;这样更方便…

右玉200MW光伏电站项目 微气象、安全警卫、视频监控系统

一、项目名称 山西右玉200MW光伏电站项目 微气象、安全警卫、视频监控系统 二、项目背景&#xff1a; 山西右玉光伏发电项目位于右玉县境内&#xff0c;总装机容量为200MW&#xff0c;即太阳能电池阵列共由200个1MW多晶硅电池阵列子方阵组成&#xff0c;每个子方阵包含太阳能…

Java基础学习:java常用启动命令

一、java -jar 1、系统属性传递 使用形式&#xff1a;java -DpathD:\jacoco -jar 获取方式&#xff1a;System.getProperties() 2、系统参数传递 使用形式&#xff1a;java -jar application.jar --jacocoPathD:\tomcat 获取方式&#xff1a;通过启动方法入口main的参数arg…

一级考试真题(2019)

一级考试真题&#xff08;2019&#xff09;

echarts图表自定义配置(二)——代码封装

下图是初版&#xff0c;火山图的代码。可以看出&#xff0c;里面的变量&#xff0c;逻辑&#xff0c;函数存在冗余&#xff0c;基本上都是改了参数&#xff0c;同样的get和set&#xff0c;去刷新图表&#xff1b;对于往后继续开发十几二十个图表&#xff0c;会很麻烦。因此需要…

如何用状态图进行设计05

到目前为止&#xff0c;我们已经讨论了状态图的原理。这些原理对状态图和扩展状态图都适用。第二章后面的部分主要讲述了扩展状态图的扩展功能。我们将围绕这些增强的功能&#xff0c;使你对BetterState Pro的设计能力有很好的了解。 关于这些内容和其他有关扩展状态图特性的完…

鸿蒙NEXT开发案例:九宫格随机

【引言】 在鸿蒙NEXT开发中&#xff0c;九宫格抽奖是一个常见且有趣的应用场景。通过九宫格抽奖&#xff0c;用户可以随机获得不同奖品&#xff0c;增加互动性和趣味性。本文将介绍如何使用鸿蒙开发框架实现九宫格抽奖功能&#xff0c;并通过代码解析展示实现细节。 【环境准…

【efinance一个2k星的库】

efinance 是一个可以快速获取基金、股票、债券、期货数据的 Python 库&#xff0c;回测以及量化交易的好帮手 但没有等比复权的&#xff0c;不用。 import efinance as ef ef.stock.get_quote_history(510880,fqt2)

协同办公软件新升级:细节优化,让办公更简单

细节决定成败&#xff0c;企业酷信协同办公系统通过贴近客户实际需求的一系列改进和创新&#xff0c;在技术架构、系统结构、管理理念和使用性能上&#xff0c;都达到了国内先进水平&#xff0c;同时具备独特的优势。让我们看看企业酷信是如何通过这些细节提升&#xff0c;为企…

【AI知识】有监督学习分类任务之支持向量机

1.支持向量机概念 支持向量机&#xff08;Support Vector Machine, SVM&#xff09; 是一种有监督学习算法&#xff0c;主要用于分类任务&#xff08;也可用于回归任务&#xff0c;即支持向量回归&#xff0c;SVR&#xff09;。SVM的核心思想是找到一个最优的超平面&#xff0…

MySQL有哪些高可用方案?

大家好&#xff0c;我是锋哥。今天分享关于【MySQL有哪些高可用方案?】面试题。希望对大家有帮助&#xff1b; MySQL有哪些高可用方案? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 MySQL 高可用方案旨在确保数据库系统的高可靠性、低宕机时间、以及在硬件故障…

利用Docker分层构建优化镜像大小

合适docker镜像文件大小不仅影响容器启动效率&#xff0c;也影响资源占用效率。本文介绍如何利用分层方式构建docker镜像&#xff0c;采用多种方式避免镜像文件太大而影响性能。 Docker 镜像大小优化的重要性 资源利用效率 较小的镜像文件在存储和传输过程中占用更少的空间和带…

threejs——无人机概念切割效果

主要技术采用着色器的切割渲染,和之前写的风车可视化的文章不同,这次的切割效果是在着色器的基础上实现的,并新增了很多可调节的变量,兄弟们,走曲儿~ 线上演示地址,点击体验 源码下载地址,点击下载 正文 从图中大概可以看出以下信息,一个由线组成的无人机模型,一个由…

我的AI工具箱Tauri版-SpiderYtDlp油管视频多功能下载

本教程基于自研的AI工具箱Tauri版进行SpiderYtDlp油管视频多功能下载。 SpiderYtDlp油管视频多功能下载 是一款基于自研AI工具箱的全新解决方案&#xff0c;专为满足多场景需求的用户设计。工具集成了便捷的链接直接下载功能和强大的关键词模糊搜索下载功能&#xff0c;赋能创…

PyCharm如何导入库( 包 )

目录 1.在主界面中导库 2.用设置->项目安装库 2.1.使用右上方按钮 2.2.使用右下方Python解释器 3.使用左下角终端导库 1.在主界面中导库 在主界面输入导库后等待一会儿&#xff0c;会在那一行出现一个红色灯。 图1 红色灯 我们点击红色灯&#xff0c;会出现 图2 错误选…

Bananna Pi开源社区联合矽昌通信打造开源的低成本Wifi5路由器

香蕉派 BPI-Wifi5 路由器采用矽昌SF19A2890S2芯片方案设计。它是一款高性能无线路由器&#xff0c;适用于小微企业、家庭和其他网络环境。Banana Pi开源社区提供整体解决方案。所有代码开源&#xff0c;用户可以在上面自由开发自己的应用。 Banana Pi wifi5 路由器github代码: …

Spring Boot教程之二十五: 使用 Tomcat 部署项目

Spring Boot – 使用 Tomcat 部署项目 Spring Boot 是一个基于微服务的框架&#xff0c;在其中创建可用于生产的应用程序只需很少的时间。Spring Boot 建立在 Spring 之上&#xff0c;包含 Spring 的所有功能。如今&#xff0c;它正成为开发人员的最爱&#xff0c;因为它是一个…

scale index的计算

scale index定义 基本实现 需要注意&#xff0c;scale index的提出者分别构建了MATLAB和R语言的实现方式。 但是&#xff0c;需要注意&#xff0c;经过我向作者求证。 MATLAB编写的代码已经“过时了”&#xff0c;为了拥抱时代&#xff0c;作者构建了R语言包&#xff0c;名称为…

虚幻5描边轮廓材质

很多游戏内都有这种描边效果&#xff0c;挺实用也挺好看的&#xff0c;简单复刻一下 效果演示&#xff1a; Linethickness可以控制轮廓线条的粗细 这样连完&#xff0c;然后放到网格体细节的覆层材质上即可 可以自己更改粗细大小和颜色