MyBatis Plus

Posted 做梦追仙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis Plus相关的知识,希望对你有一定的参考价值。

概述MyBatis-Plus

MyBatis-Plus简称 MP是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开
发、提高效率而生
官方文档:https://baomidou.com/

Hello MP

添加依赖

<!-- 如果没有整合SpringBoot,则需要引入这个依赖,通过注解进行开发,并手工添加所需要的配置
-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.3.1</version>
</dependency>

使用MP可以有对应的映射文件,也可以没有映射文件

  • 如果需要对sql语句进行优化,则可以添加映射元文件;如果没有需要sql语句优化,则省略
    mapper.xml文件
    • 在 MyBatis 的基础上只做增强不做改变。过去MyBatis的用法在MP中仍旧有效
  • 具体执行的sql语句可以由MP生成
    定义实体类
  • @TableName添加在实体类上,用于标识实体类所对应的表名注解,标识实体类对应的表
  • @TableId是主键注解,用于在属性上标识对应的注解
    • value用于指定对应的主键字段名,如果不指定,则和属性名称一致
    • type是IdType枚举类型,用于指定主键生成策略
      • AUTO数据库ID自增
      • NONE意思是无状态,该类型为未设置主键类型。注解里等于跟随全局,全局里约等于
        INPUT
      • INPUT是在执行insert操作之前自行 set 主键值
      • ASSIGN_ID采用雪花算法生成主键值,应该是string类型
      • ASSIGN_UUID采用UUID生成字符串值充当主键
    • 不建议使用的三种算法:ID_WORKER分布式全局唯一 ID 长整型类型、UUID是32位UUID字
      符串、ID_WORKER_STR是分布式全局唯一 ID 字符串类型
  • @TableField属性上的针对字段的注解,用于非主键类型的属性
    • value用于定义当前属性对应的数据库字段名
    • exist标识该属性是否为数据库表字段,因为如果不加配置则默认属性都是有同名的对应字段
    • jdbcType用于声明对应的JDBC 类型,该默认值不代表会按照该值生效
    • numericScale用于指定小数点后保留的位数
@Data
@TableName("tb_users")
public class User implements Serializable 
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private String password;
@TableField(exist = false)
private String repassword;
private String email;

添加mapper接口,注意使用MP时mapper.xml可有可无

  • MP提供了一个父接口BaseMapper,其中包含了常见的CRUD的方法
public interface UserMapper extends BaseMapper<User> 

使用自动扫描进行mapper接口的注册,在主类上添加自动扫描注解即可

@MapperScan("com.yan.dao")
@SpringBootApplication
public class DemoApplication

MP针对业务层提供了IService接口,和对应的实现类ServiceImpl,在具体开发中可以通过继承IService
接口来定义业务接口

public interface IUserServ extends IService<User> 

定义业务实现类

@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
@Service
public class UserServImpl extends ServiceImpl<UserMapper, User> implements
IUserServ 

在控制台上打印输入所执行的sql语句

mybatis-plus.configuration.logimpl=org.apache.ibatis.logging.stdout.StdOutImpl

IService业务接口

一般使用步骤:
定义特定接口,这个接口用于定义特殊的方法,一般通用方法从MP提供的IService接口种继承

public interface UserService extends IService<User> 

定义具体的业务实现类,通用方法的定义是MP提供的父类ServiceImpl,泛型1是当前业务类需要使用的
Mapper接口,泛型2是对应的实体类

public class UserServiceImpl extends ServiceImpl ServiceImpl<UserMapper,
User> implements UserService

接口定义

public interface IService<T> 
//插入一条记录(选择字段,策略插入),非空属性参与生成sql语句,否则不出现。default才
能生效
default boolean save(T entity) 
return SqlHelper.retBool(getBaseMapper().insert(entity));

//插入批量,一次性提供1000条sql语句,使用注解设置所有的异常都执行回滚
@Transactional(rollbackFor = Exception.class)
default boolean saveBatch(Collection<T> entityList) 
return saveBatch(entityList, DEFAULT_BATCH_SIZE);

//根据ID列执行删除 DELETE FROM tb_users WHERE id=?
default boolean removeById(Serializable id) 
return SqlHelper.retBool(getBaseMapper().deleteById(id));

//根据实体的ID删除,其他的属性无效 DELETE FROM tb_users WHERE id=?
default boolean removeById(T entity) 
return SqlHelper.retBool(getBaseMapper().deleteById(entity));

//根据columnMap条件执行删除记录,其中的key为列名称,value标识条件为列名称=value
值,所有的key/value对是and连接 DELETE FROM tb_users WHERE role_id = ? AND sex
= ? AND id = ?
default boolean removeByMap(Map<String, Object> columnMap) 
Assert.notEmpty(columnMap, "error: columnMap must not be empty");
return SqlHelper.retBool(getBaseMapper().deleteByMap(columnMap));

//根据实体对象的查询条件执行删除记录,删除条件封装在QueryWrapper对象中
default boolean remove(Wrapper<T> queryWrapper) 
return SqlHelper.retBool(getBaseMapper().delete(queryWrapper));

基本用法:
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.eq("sex",true).between("id",10,30).or().like("username","zhang");
boolean removed = userService.remove(wrapper);
System.out.println(removed);
所执行的sql语句:
==> Preparing: DELETE FROM tb_users WHERE (sex = ? AND id BETWEEN ? AND ?
OR username LIKE ?)
==> Parameters: true(Boolean), 10(Integer), 30(Integer), %zhang%(String)
<== Updates: 0
//批量删除,参数是要删除数据的id所构成的集合
default boolean removeByIds(Collection<?> list) 
if (CollectionUtils.isEmpty(list)) 
return false;

return SqlHelper.retBool(getBaseMapper().deleteBatchIds(list));

//根据ID选择修改实体类中的所有非空属性,如果属性为空则不参与修改,值仍旧为原来的数据
default boolean updateById(T entity) 
return SqlHelper.retBool(getBaseMapper().updateById(entity));

基础用法:
User tmp=new User();
tmp.setId(2L);
tmp.setUsername("王胡子");
boolean res = userService.updateById(tmp);
所执行的sql语句:
==> Preparing: UPDATE tb_users SET username=? WHERE id=?
==> Parameters: 王胡子(String), 2(Long)
<== Updates: 1
//具体的修改是通过UpdateWrapper对象进行封装,更新记录,需要设置sqlset
*
* @param updateWrapper 实体对象封装操作类 @link
com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper
*/
default boolean update(Wrapper<T> updateWrapper) 
return update(null, updateWrapper);

基础用法:
User tmp=new User();
tmp.setId(2L);
tmp.setUsername("王胡子");
boolean res = userService.updateById(tmp);
所执行的sql语句:
==> Preparing: UPDATE tb_users SET username=? WHERE id=?
==> Parameters: 王胡子(String), 2(Long)
<== Updates: 1
基础用法:
UpdateWrapper<User> wrapper=new UpdateWrapper<>();
//set用于定义需要修改的列和对应的新值
wrapper.set("username","贺老总");
wrapper.set("password","666666");
//和QueryWrapper一样定义对应的修改条件
wrapper.between("id",10,20);
boolean res = userService.update(wrapper);
所执行的sql语句:
==> Preparing: UPDATE tb_users SET username=?,password=? WHERE (id BETWEEN
? AND ?)
==> Parameters: 贺老总(String), 666666(String), 10(Integer), 20(Integer)
<== Updates: 0
//一组实体对象的集合根据每个对象的ID批量更新
@Transactional(rollbackFor = Exception.class)
default boolean updateBatchById(Collection<T> entityList) 
return updateBatchById(entityList, DEFAULT_BATCH_SIZE);

//根据参数entity的id属性值判断执行save或者update操作。TableId 注解存在更新记录,
否插入一条记录
boolean saveOrUpdate(T entity);
调用语句1User tmp=new User();
tmp.setUsername("爱新觉罗");
tmp.setPassword("666666");
tmp.setRoleId(2L);
boolean res = userService.saveOrUpdate(tmp);
多执行的sql语句:
==> Preparing: INSERT INTO tb_users ( username, password, role_id ) VALUES
( ?, ?, ? )
==> Parameters: 爱新觉罗(String), 666666(String), 2(Long)
<== Updates: 1
调用语句2:这里不同于语句1的是id有值
User tmp=new User();
tmp.setId(3L);
tmp.setUsername("爱新觉罗");
tmp.setPassword("666666");
tmp.setRoleId(2L);
boolean res = userService.saveOrUpdate(tmp);
所执行的sql语句:
首先按照id执行查询,如果有返回数据则执行修改操作
==> Preparing: SELECT id,username,password,birth,sex,role_id FROM tb_users
WHERE id=?
==> Parameters: 3(Long)
<== Columns: id, username, password, birth, sex, role_id
<== Row: 3, yan222, 888888, 2021-08-25, 1, 4
<== Total: 1
修改操作
==> Preparing: UPDATE tb_users SET username=?, password=?, role_id=? WHERE
id=?
==> Parameters: 爱新觉罗(String), 666666(String), 2(Long), 3(Long)
<== Updates: 1
如果查询不到数据,则执行插入操作
==> Preparing: INSERT INTO tb_users ( id, username, password, role_id )
VALUES ( ?, ?, ?, ? )
==> Parameters: 300(Long), 爱新觉罗(String), 666666(String), 2(Long)
<== Updates: 1
//根据 ID 查询
default T getById(Serializable id) 
return getBaseMapper().selectById(id);

//按照id的集合进行查询(根据ID 批量查询),类似于id in (集合)
default List<T> listByIds(Collection<? extends Serializable> idList) 
return getBaseMapper().selectBatchIds(idList);
//查询(根据 columnMap 条件),Map中key为列名称,value是对应的值,多个key/value
之间使用and连接
default List<T> listByMap(Map<String, Object> columnMap) 
return getBaseMapper().selectByMap(columnMap);

//根据Wrapper查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件
wrapper.last("LIMIT 1")
default T getOne(Wrapper<T> queryWrapper) 
return getOne(queryWrapper, true);

//查询总记录数,类似于select count(*) from... where 1=1
default long count() 
return count(Wrappers.emptyWrapper());

//根据Wrapper查询条件,查询总记录数 类似于select count(*) from ... where
...
default long count(Wrapper<T> queryWrapper) 
return
SqlHelper.retCount(getBaseMapper().selectCount(queryWrapper));

//按照查询条件queryWrapper执行查询,获取多行数据,每行数据转换为一个值bean,返回查
询列表
default List<T> list(Wrapper<T> queryWrapper) 
return getBaseMapper().selectList(queryWrapper);

//查询所有
default List<T> list() 
return list(Wrappers.emptyWrapper());

//按照查询条件queryWrapper执行物理的分页查询
default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) 
return getBaseMapper().selectPage(page, queryWrapper);

调用语句
//查询条件
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.like("username","zhangsan");//模糊查询
wrapper.gt("id",10);//id大于10,多个条件之间没有使用or()则为and连接
wrapper.between("birth",new java.sql.Date(1900-1900,1-1,1),new
java.sql.Date(2050-1900,2-1,15));
wrapper.or().in("sex",true,false);
//构建分页条件,参数1是页码值,参数2是每页行数
IPage<User> page= Page.of(50,2);
page=userService.page(page,wrapper)Mybatis-Plus:快速开始(SpringBoot + Mybatis + Mybatis)

Mybatis-Plus学习笔记

改mybatis到mybatis-plus的擎天巨坑

Mybatis-Plus入门学习笔记

MyBatis Plus

java mybatisplus