Mybatis-plus详解

搭建环境

创建表

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user`  (
  `id` int(11) AUTO_INCREMENT PRIMARY KEY,
  `phone` varchar(11) UNIQUE NOT NULL,
  `user_name` varchar(20),
  `age` int(2),
  `is_deleted` int(11) NULL DEFAULT 0
)

创建SpringBoot工程,然后引入依赖
SpringBoot版本是2.7.5。

	<dependencies>
        <!-- SpringBoot依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 小辣椒 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- mybatis-plus依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
    </dependencies>

配置application.properties文件

server.port=8081
# 数据库的配置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/db_csdn?SSL=false&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.password=123456
spring.datasource.username=root
# 日志输出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

添加实体类

下面注解会在后面给大家说,这里不必追究。

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
    @TableId(value = "id") // 人只有一个value属性,则默认是省略的。
    private Integer id;
    @TableField("user_name")
    private String userName;
    private String phone;
    @TableLogic
    private Integer isDeleted;
}

Mapper类

public interface UserMapper extends BaseMapper<User> {
}

测试搭建的环境

@Test
public void testInsert(){
    User user = new User();
    user.setUserName("老刘");
    user.setPhone("13423458945");
    userMapper.insert(user);
}

常用注解

@TableName

描述表名注解,标识实体类对应的表
使用位置实体类

代码实现:

@TableName("t_user")
public class User {
}

@TableId

描述主键注解
使用位置实体类的主键字段

注意:如果主键名与实体类对应的属性名不一致,则必须要有value属性,如果只有value一个属性,则可以省略不写。

属性类型必须指定默认值描述
valueString“”主键字段名
typeEnumIdType.NONE指定主键类型

IdType类型有以下

描述
AUTO数据库 ID 自增,使用前数据库的id必须是自增的
ASSIGN_ID分配ID,默认是雪花算法生成id,与数据库的id是否自增无关
INPUTinsert 前自行 set 主键值
ASSIGN_UUID分配 UUID

代码实现:

@TableName("t_user")
public class User {
 	@TableId(value = "id",type = IdType.AUTO) // 人只有一个value属性,则默认是省略的。
    private Integer id;
}

@TableField

描述字段注解(非主键)
使用位置实体类的非主键字段

注意

  1. 如果属性名与实体类对应的属性名不一致,则必须要有value属性,如果只有value一个属性,则可以省略不写。

  2. 如果实体类中的属性使用的是驼峰命名风格,而表中的字段使用的是下划线命名风格,那么Mybatis-plus会自动将下划线命名风格转换为驼峰命名风格

代码实现:

@TableName("t_user")
public class User {
    @TableId(value = "id",type = IdType.AUTO) // 人只有一个value属性,则默认是省略的。
    private Integer id;
    @TableField(value = "user_name",exist = true) // 如果exist的属性为false,则意思是不是数据库中的字段
    private String userName;
}

@TableLogic

描述表字段逻辑处理注解(逻辑删除)

属性类型必须指定默认值描述
valueString“”逻辑未删除值
delvalString“”逻辑删除值

逻辑删除和物理删除的概念:
逻辑删除假删除,将对应数据中代表是否被删除字段(is_deleted)的状态修改为被删除状态(值为1),但是在数据库中仍然能看到此条记录。

物理删除真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据。
使用场景:可以进行数据的恢复

使用全局配置解决表名前缀和主键策略

# 配置MyBatis-Plus的主键策略
mybatis-plus.global-config.db-config.id-type=assign_id
# 配置MyBatis-Plus操作表的默认前缀
mybatis-plus.global-config.db-config.table-prefix=t_

CRUD接口

Mapper CRUD接口

BaseMapper接口为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器。其中泛型 T为任意实体对象。

方法如下
在这里插入图片描述

BaseMapper的源码

public interface BaseMapper<T> extends Mapper<T> {

    /**
     * 插入一条记录
     *
     * @param entity 实体对象
     */
    int insert(T entity);

    /**
     * 根据 ID 删除
     *
     * @param id 主键ID
     */
    int deleteById(Serializable id);

    /**
     * 根据实体(ID)删除
     *
     * @param entity 实体对象
     * @since 3.4.4
     */
    int deleteById(T entity);

    /**
     * 根据 columnMap 条件,删除记录
     *
     * @param columnMap 表字段 map 对象
     */
    int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

    /**
     * 根据 entity 条件,删除记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
     */
    int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 删除(根据ID或实体 批量删除)
     *
     * @param idList 主键ID列表或实体列表(不能为 null 以及 empty)
     */
    int deleteBatchIds(@Param(Constants.COLL) Collection<?> idList);

    /**
     * 根据 ID 修改
     *
     * @param entity 实体对象
     */
    int updateById(@Param(Constants.ENTITY) T entity);

    /**
     * 根据 whereEntity 条件,更新记录
     *
     * @param entity        实体对象 (set 条件值,可以为 null)
     * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
     */
    int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);

    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     */
    T selectById(Serializable id);

    /**
     * 查询(根据ID 批量查询)
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    List<T> selectBatchIds(@Param(Constants.COLL) Collection<? extends Serializable> idList);

    /**
     * 查询(根据 columnMap 条件)
     *
     * @param columnMap 表字段 map 对象
     */
    List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

    /**
     * 根据 entity 条件,查询一条记录
     * <p>查询一条记录,例如 qw.last("limit 1") 限制取一条记录, 注意:多条数据会报异常</p>
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    default T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper) {
        List<T> ts = this.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(ts)) {
            if (ts.size() != 1) {
                throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records");
            }
            return ts.get(0);
        }
        return null;
    }

    /**
     * 根据 Wrapper 条件,判断是否存在记录
     *
     * @param queryWrapper 实体对象封装操作类
     * @return 是否存在记录
     */
    default boolean exists(Wrapper<T> queryWrapper) {
        Long count = this.selectCount(queryWrapper);
        return null != count && count > 0;
    }

    /**
     * 根据 Wrapper 条件,查询总记录数
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    Long selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 entity 条件,查询全部记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询全部记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询全部记录
     * <p>注意: 只返回第一个字段的值</p>
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 entity 条件,查询全部记录(并翻页)
     *
     * @param page         分页查询条件(可以为 RowBounds.DEFAULT)
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    <P extends IPage<T>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询全部记录(并翻页)
     *
     * @param page         分页查询条件
     * @param queryWrapper 实体对象封装操作类
     */
    <P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}

插入

插入一条数据

@Resource
private UserMapper userMapper;
@Test
public void testInsert(){
    User user = new User();
    user.setUserName("老黑");
    user.setPhone("13523458945");
    userMapper.insert(user);
    System.out.println("获取的id" + user.getId());
}

结果:我们发现在插入数据时,是基于雪花算法的策略生成id。并且它会将主键id存到实体类中。

生成的sql语句

INSERT INTO t_user ( user_name, phone ) VALUES ( ?, ? )

删除

通过id删除

@Resource
private UserMapper userMapper;
@Test
public void testDeleteById(){
    int result = userMapper.deleteById(2140147718);
    System.out.println("受影响行数:" + result);
}

生成的sql语句

UPDATE t_user SET is_deleted=1 WHERE id=? AND is_deleted=0

通过id批量删除

@Resource
private UserMapper userMapper;
@Test
public void testDeleteById(){
   List<Integer> list = Arrays.asList(1, 2, 3);
   int result = userMapper.deleteBatchIds(list);
   System.out.println("受影响行数:" + result);
}

生成的sql语句

UPDATE t_user SET is_deleted=1 WHERE id IN ( ? , ? , ? ) AND is_deleted=0

通过Map条件删除

@Resource
private UserMapper userMapper;
@Test
public void testDeleteMap(){
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("phone","15623458945");
    hashMap.put("user_name","李四");
    int result = userMapper.deleteByMap(hashMap);
    System.out.println("受影响行数:" + result);
}

生成的sql语句

UPDATE t_user SET is_deleted=1 WHERE phone = ? AND user_name = ? AND is_deleted=0

修改

通过id修改信息

@Resource
private UserMapper userMapper;
@Test
public void testUpdateById(){
    User user = new User();
    user.setId(110100482);
    user.setUserName("李四");
    user.setPhone("18954687536");
    int result = userMapper.updateById(user);
    System.out.println("受影响行数:" + result);
}

生成的sql语句

UPDATE t_user SET user_name=?, phone=? WHERE id=? AND is_deleted=0

查询

根据id查询用户信息

@Resource
private UserMapper userMapper;
@Test
public void testSelectById(){
    User user = userMapper.selectById(1);
    System.out.println(user);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE id=? AND is_deleted=0

根据多个id查询多个用户信息

@Resource
private UserMapper userMapper;
@Test
public void testSelectMoreId(){
    List<Integer> list = Arrays.asList(1, 2, 3);
    List<User> userList = userMapper.selectBatchIds(list);
    for (User user : userList) {
        System.out.println(user);
    }
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE id IN ( ? , ? , ? ) AND is_deleted=0

根据Map条件查询用户信息

@Resource
private UserMapper userMapper;
@Test
public void testSelectByMap(){
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("phone","15586264781");
    hashMap.put("name","王五");
    List<User> userList = userMapper.selectByMap(hashMap);
    for (User user : userList) {
        System.out.println(user);
    }
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE phone = ? AND user_name = ? AND is_deleted=0

查询所有用户信息

@Resource
private UserMapper userMapper;
@Test
public void testSelectList(){
	// 这里的参数是Wrapper类型,即为条件构造器,这个是针对Sql语句设置不同的条件,如果没有条件,可以设为null。后面会说的。
    List<User> userList = userMapper.selectList(null);
    for (User user : userList) {
        System.out.println(user);
    }
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0

Service CRUD接口

通用 Service CRUD 封装IService接口和其实现类ServiceImpl,其中T为任意的实体对象。

IService部分方法如下所示,由于方法太多了,这里只列举一部分,剩余的可以自己看源码。
在这里插入图片描述

ServiceImpl方法如下所示
在这里插入图片描述

注意: ServiceImpl实现了IService,提供了IService中基础功能的实现。当然,也可以自定义相应的业务方法完成需求。

由于通用Service中CRUD的方法与通用Mapper中CRUD方法类似,这里只列举不同的。

批量添加

@Resource
private UserService userService;
@Test
public void testSaveBatch(){
    ArrayList<User> list = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        User user = new User();
        user.setPhone("1594561234" + i);
        user.setUserName("张三" + i);
        list.add(user);
    }
    userService.saveBatch(list);
}

生成的sql语句

INSERT INTO t_user ( user_name, phone ) VALUES ( ?, ? )

查询总记录数

@Resource
private UserService userService;
@Test
public void testCount(){
    long count = userService.count();
    System.out.println("总记录数:" + count);
}

生成的sql语句

SELECT COUNT( * ) FROM t_user WHERE is_deleted=0

条件构造器

在这里插入图片描述

AbstractWrapper中的部分方法以及QueryMapper的使用

提示:有的方法会有 boolean condition,也就是表示该条件是否加入最后生成的sql中。默认为true。

allEq

boolean null2IsNull参数:默认为true。若为true,则在map的value为null时调用isNull方法;若为false,则忽略value为null的

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper1(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("phone","15623458964");
    hashMap.put("user_name",null);
    wrapper.allEq(hashMap,false); // SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (phone = ?)
    //wrapper.allEq(false,hashMap,false); // SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0
    List<User> list = userMapper.selectList(wrapper);
    for (User user : list) {
        System.out.println(user);
    }
}

生成的sql语句看后面的注释

eq 和 ne

eq:等于 =
ne:不等于 <>

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper2(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("phone","15623458964")..ne("user_name","张三");
    User user = userMapper.selectOne(wrapper);
    System.out.println(user);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (phone = ? AND user_name <> ?)

gt 和 lt

gt:大于 >
lt: 小于 <

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper3(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.gt("id","110100481").lt("id","227540995");
    List<User> users = userMapper.selectList(wrapper);
    users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (id > ? AND id < ?)

ge 和 le

ge:大于等于 >=
le: 小于等于 <=

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper4(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.ge("id","110100481").le("id","227540995");
    List<User> users = userMapper.selectList(wrapper);
    users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (id >= ? AND id <= ?)

between 和 notBetween

between :BETWEEN 值1 AND 值2
notBetween:NOT BETWEEN 值1 AND 值2

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper5(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.between("id","110100481","227540995")
             .notBetween("phone","1695567000","1995567000");
     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (id BETWEEN ? AND ? AND phone NOT BETWEEN ? AND ?)

like 和 notLike

LIKE:%值%
notLike:NOT LIKE ‘%值%’

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper6(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.like("user_name","张")
             .notLike("phone","169");
     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (user_name LIKE ? AND phone NOT LIKE ?)

likeLeft 和 likeRight

likeLeft :LIKE '%值' likeRight`:LIKE ‘值%’

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper7(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.likeLeft("user_name","张")
             .likeRight("phone","134");
     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (user_name LIKE ? AND phone LIKE ?)

isNull 和 isNotNull

isNull:字段 IS NULL
isNotNull:字段 IS NOT NULL

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper8(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.isNull("user_name").isNotNull("phone");
     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (user_name IS NULL AND phone IS NOT NULL)

in 和notIn

in:字段 IN
notIn:字段 NOT IN

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper9(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.in("phone", Arrays.asList("15945612354","15945612355","15945612356"))
                .notIn("user_name","张三","李四");
     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (phone IN (?,?,?) AND user_name NOT IN (?,?))

groupBy

groupBy:分组:GROUP BY 字段

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper10(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.groupBy("user_name");
     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 GROUP BY user_name

orderByAsc 和 orderByDesc

orderByAsc:排序:ORDER BY 字段, … ASC
orderByDesc:排序:ORDER BY 字段, … DESC

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper11(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.orderByAsc("id").orderByDesc("phone");
     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 ORDER BY id ASC,phone DESC

orderBy

orderBy:排序:ORDER BY 字段,

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper12(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.orderBy(true,true,"id");
     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 ORDER BY id ASC

having

having:HAVING ( sql语句 )

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper13(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.groupBy("phone").having("phone > 15945612342");
     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 GROUP BY phone HAVING phone > 15945612342

or 和 and

or:OR 嵌套
and:AND 嵌套

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper14(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.eq("user_name","张三").or().isNull("phone")
                .and(wrappers -> {
                    wrappers.eq("phone","15945612342");
                });     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (user_name = ? OR phone IS NULL AND (phone = ?))

inSql 和 notInSql

inSql:字段 IN ( sql语句 )
notInSql:字段 NOT IN ( sql语句 )

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper14(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.notInSql("id","select id from t_user where id <= 2123419651")
                .inSql("phone","select phone from t_user where phone <= 15245612344");    List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (id NOT IN (select id from t_user where id <= 2123419651) AND phone IN (select phone from t_user where phone <= 15245612344))

select方法

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper15(){
     QueryWrapper<User> wrapper = new QueryWrapper<>();
     wrapper.select("user_name");
     // selectMaps返回Map集合列表,通常配合select使用,可以省去没有查询到的列值。
     List<Map<String, Object>> users = userMapper.selectMaps(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT user_name FROM t_user WHERE is_deleted=0

UpdateWrapper的使用

代码实现:

@Resource
private UserMapper userMapper;
@Test
public void testUpdateWrapper16(){
     UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
     updateWrapper.set("phone","15478965231").eq("id","110100482");
     int result = userMapper.update(null, updateWrapper);
     System.out.println(result);
}

生成的sql语句

UPDATE t_user SET phone=? WHERE is_deleted=0 AND (id = ?)

LambdaQueryWrapper

@Resource
private UserMapper userMapper;
@Test
public void testSelectWrapper17(){
     User user = new User();
     user.setPhone("159");
     LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
     wrapper.like(User::getPhone,user.getPhone());
     List<User> users = userMapper.selectList(wrapper);
     users.forEach(System.out::println);
}

生成的sql语句

SELECT id,user_name,phone,is_deleted FROM t_user WHERE is_deleted=0 AND (phone LIKE ?)

LambdaUpdateWrapper

@Resource
private UserMapper userMapper;
@Test
public void testUpdateWrapper18(){
     LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
     wrapper.set(User::getUserName,"李四").eq(User::getId,"227540993");
     int result = userMapper.update(null, wrapper);
     System.out.println(result);
}

生成的sql语句

UPDATE t_user SET user_name=? WHERE is_deleted=0 AND (id = ?)

分页插件

使用Mybatis-Plus自带的分页

①:添加分页的配置类

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}

②:进行测试

@Test
public void testPage(){
    Page<User> page = new Page<>(1,5);
    userMapper.selectPage(page,null);
    List<User> records = page.getRecords();
    System.out.println("第一页的所有记录:");
    records.forEach(System.out::println);
    System.out.println("总页数" + page.getPages());
    System.out.println("总记录数" + page.getTotal());
    System.out.println("每页显示的条数" + page.getSize());
    System.out.println("当前页" + page.getCurrent());
    System.out.println("是否有上一页:"+page.hasPrevious());
    System.out.println("是否有下一页:"+page.hasNext());
}

使用mapper.xml文件自定义分页

①:添加分页的配置类

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}

②:UserMapper接口

public interface UserMapper extends BaseMapper<User> {
    Page<User> selectPageVo(@Param("page") Page<User> page,@Param("name") String name);
}

③:UserMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhang.mapper.UserMapper">
    <select id="selectPageVo" resultType="User">
        select * from t_user where user_name = #{name}
    </select>
</mapper>

④:在application.properties文件中配置Mybatis-Plus的相关配置

# 配置别名
mybatis-plus.type-aliases-package=com.zhang.pojo
# 配置mapper文件
mybatis-plus.mapper-locations=classpath:/mapper/**.xml

⑤:进行测试

@Test
public void testPage(){
    Page<User> page = new Page<>(1,5);
    userMapper.selectPageVo(page,"张三");
    List<User> records = page.getRecords();
    System.out.println("第一页的所有记录:");
    records.forEach(System.out::println);
    System.out.println("总页数" + page.getPages());
    System.out.println("总记录数" + page.getTotal());
    System.out.println("每页显示的条数" + page.getSize());
    System.out.println("当前页" + page.getCurrent());
    System.out.println("是否有上一页:"+page.hasPrevious());
    System.out.println("是否有下一页:"+page.hasNext());
}

乐观锁插件

乐观锁和悲观锁的概念:

  1. 乐观锁指别人不会同时修改数据,默认是不会上锁的,只是在执行的时候会判断别人在此刻是否修改了数据,如果修改了数据,则放弃操作,否则执行操作
  2. 悲观锁指别人会同时修改数据,默认是在操作数据时是上锁的,直到操作完成后才会释放所,在上锁期间其他人不能操作数据。

实现流程
3. 取出记录时,会获取到当前的version。
4. 更新记录时,会带上这个version。
5. 执行更新时,会将version的版本+1。如果version版本不对,则更新失败。

实现步骤

首先在数据库中添加version字段。

①:在实体类的 version 属性上加上 @Version注解。

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
    @TableId(value = "id",type = IdType.AUTO) // 人只有一个value属性,则默认是省略的。
    private Integer id;
    @TableField(value = "user_name",exist = true) // 如果exist的属性为false,则意思是不是数据库中的字段
    private String userName;
    private String phone;
    private SexEnum sex;
    @TableLogic
    private Integer isDeleted;
    @Version
    private Integer version;
}

②:基于注解配置

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

案例:这里有A、B、C三个人,其中C刚开始想让A帮他修改手机号,然后A说等一会在去。过了一会想换一个手机号,于是C就让B去帮他换新手机号。此时,A和B同时帮C修改手机号,那么原本C最终想要的是B帮忙修改的手机号,结果在B改完后,A又改了,那么此时就造成了结果误差,此时A就把B的操作覆盖了。我们将会使用乐观锁的插件来解决。

代码实现

将@Version注解与注解配置都配置好后,进行下述测试。

@Resource
private UserMapper userMapper;
 @Test
public void testLock(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // A
    User a = userMapper.selectOne(wrapper.eq("user_name", "C"));
    System.out.println("此时A查到C的手机号" + a.getPhone());
    // B
    User b = userMapper.selectOne(wrapper.eq("user_name", "C"));
    System.out.println("此时B查到C的手机号" + a.getPhone());
    // 此时B修改手机号
    b.setPhone("15978651234");
    int resultB = userMapper.updateById(b);  // 1
    System.out.println("B修改手机号的结果:" + resultB);
    // 此时A修改手机号
    a.setPhone("19878651234");
    int resultA = userMapper.updateById(a);  // 0
    System.out.println("A修改手机号的结果:" + resultA);

    // 最后的结果
    User c = userMapper.selectOne(wrapper.eq("user_name", "C"));
    System.out.println("C最终的手机号:" + c.getPhone());
}

通用枚举

表中的有些字段值是固定的,例如性别(男或女),例如我们可以使用Mybatis-Plus的通用枚举来实现。

注意:从 3.5.2 版本开始只需完成 声明通用枚举属性 即可使用。

①:给数据库表添加字段sex
在这里插入图片描述
②:创建通用枚举类型

public enum SexEnum {
    MALE(1,"男"),
    FEMALE(2,"女");
    @EnumValue
    private Integer sex;
    @JsonValue  // 标记响应json值
    private String sexName;
    SexEnum(Integer sex, String sexName) {
        this.sex = sex;
        this.sexName = sexName;
    }

    public String getSexName() {
        return sexName;
    }
}

测试

@Resource
private UserMapper userMapper;
@Test
public void testSexNum(){
    User user = new User();
    user.setSex(SexEnum.MALE);
    user.setPhone("14536586953");
    userMapper.insert(user);
    System.out.println(userMapper.selectById(user.getId()).getSex().getSexName());
}

代码生成器

这里需要重新创建一个SpringBoot工程。

①:添加依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.2</version>
</dependency>
<dependency>
	<groupId>org.freemarker</groupId>
	<artifactId>freemarker</artifactId>
	<version>2.3.31</version>
</dependency>

②:快速生成的代码

public class TestFastAutoGenerator {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/db_csdn?SSL=false&serverTimezone=UTC","root","123456")
                .globalConfig(builder -> {
                    builder.author("zhang")  // 设置作者
                            .enableSwagger()  // 开启swagger模式
                            .fileOverride()   // 覆盖已生成文件
                            .disableOpenDir() // 禁止打开输出目录
                            .outputDir("E:\\代码\\Mybatis-plus\\csdn"); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent("src.main.java.com.zhang")  // 设置父包名
                            //.moduleName("")  // 设置父包模块名
                            .entity("entity")  // 设置包名
                            .service("service")  // 设置Service包名
                            .serviceImpl("service.impl")  // 设置serviceImpl包名
                            .controller("controller")  // 设置controller包名
                            .xml("mapper.xml")
                            .pathInfo(Collections.singletonMap(OutputFile.xml,"E:\\代码\\Mybatis-plus\\csdn\\src\\main\\java\\com\\zhang\\mapper"))// 设置mapper.xml文件生成路径
                            .pathInfo(Collections.singletonMap(OutputFile.mapper,"E:\\代码\\Mybatis-plus\\csdn\\src\\main\\java\\com\\zhang\\mapper")) // 设置mapper文件生成路径
                            .pathInfo(Collections.singletonMap(OutputFile.controller,"E:\\代码\\Mybatis-plus\\csdn\\src\\main\\java\\com\\zhang\\controller")) // 设置controller文件生成路径
                            .pathInfo(Collections.singletonMap(OutputFile.service,"E:\\代码\\Mybatis-plus\\csdn\\src\\main\\java\\com\\zhang\\service")) // 设置service文件生成路径
                            .pathInfo(Collections.singletonMap(OutputFile.serviceImpl,"E:\\代码\\Mybatis-plus\\csdn\\src\\main\\java\\com\\zhang\\service\\impl")) // 设置serviceImpl文件生成路径
                            .pathInfo(Collections.singletonMap(OutputFile.entity,"E:\\代码\\Mybatis-plus\\csdn\\src\\main\\java\\com\\zhang\\entity")); // 设置entity文件生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude("t_user")        // 设置需要生成的表名
                            .addTablePrefix("t_","c_"); // 设置过滤表前缀
                })
                .templateEngine(new FreemarkerTemplateEngine()).execute(); // 使用Freemarker引擎模板,默认是Velocity引擎模板
    }
}

③:生成的目录如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

☞^O^☜♞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值