MyBatis-Plus笔记
一、概要
1、MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变。
2、支持的数据库:mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserve。
3、Maven 依赖:
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>3.3.2</version> </dependency>
Sprinboot 的可使用
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency>
二、Helloworld(Springboot, From 官方文档)
1、 在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:
@SpringBootApplication @MapperScan("mybatisplus.springboot.mapper") public class App { public static void main(String[] args ) { SpringApplication.run(App.class, args);} }
2、 编写 Mapper 类继承 BaseMapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import mybatisplus.springboot.entity.UserPO;public interface UserMapper extends BaseMapper<UserPO>{
}
3、 通过 id 查询 User 信息
userMapper.selectById(1);
三、相关注解
@TableName 表名注解 @TableId 主键注解 @TableField 字段注解 (非主键) 属性 描述 value 数据库字段名 el 映射为原生 #{...} 逻辑, 相当于写在 xml 里的 #{...} 部分 exist 是否为数据库表字段,默认值为 true condition 字段 where 实体查询比较条件, 有值设置则按设置的值为准, 没有则为默认全局的 %s=#{%s}, 参考 update 字段 update set 部分注入, 例如:update="%s+1":表示更新时会 set version=version+1(该属性优先级高于 el 属性) insertStrategy 举例:NOT_NULL: insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>) updateStrategy 举例:IGNORED: update table_a set column=#{columnProperty} whereStrategy 举例:NOT_EMPTY: where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if> fill 字段自动填充策略 select 是否进行 select 查询 keepGlobalFormat 是否保持使用全局的 format 进行处理 jdbcType JDBC 类型 (该默认值不代表会按照该值生效) typeHandler 类型处理器 (该默认值不代表会按照该值生效) numericScale 指定小数点后保留的位数@Version 乐观锁注解
@EnumValue 通枚举类注解 (注解在枚举字段上)
@TableLogic 表字段逻辑处理注解(逻辑删除)
@SqlParser 租户注解, 支持 method 上以及 mapper 接口上
四、Mapper CRUD 接口
BaseMapper 接口,为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器
Insert // 插入一条记录 int insert(T entity);Delete
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据 ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);Update
// 根据 whereEntity 条件,更新记录
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);Select
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 查询(根据 ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
五、Service CRUD 接口
通用 Service CRUD 封装 IService 接口,进一步封装 CRUD 采用
Save // 插入一条记录(选择字段,策略插入) boolean save(T entity); // 插入(批量) boolean saveBatch(Collection<T> entityList); // 插入(批量) boolean saveBatch(Collection<T> entityList, int batchSize);SaveOrUpdate
// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据 updateWrapper 尝试更新,否继续执行 saveOrUpdate(T) 方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);Remove
// 根据 entity 条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据 ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);Update
// 根据 UpdateWrapper 条件,更新记录 需要设置 sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereEntity 条件,更新记录
boolean update(T entity, Wrapper<T> updateWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据 ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据 ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);Get
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);List
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据 ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);Page
// 无条件翻页查询
IPage<T> page(IPage<T> page);
// 翻页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件翻页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 翻页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);Count
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);Chain
query
// 链式查询 普通
QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery();
// 示例:
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list();update
// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();
// 示例:
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);
六、AbstractWrapper
用于生成 sql 的 where 条件, QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 为实现类
主要内容:
allEq 全部 eq(或个别 isNull) eq 等于 = ne 不等于 <> gt 大于 > ge 大于等于 >= lt 小于 < le 小于等于 <= between BETWEEN 值 1 AND 值 2 notBetween NOT BETWEEN 值 1 AND 值 2 like LIKE '% 值 %' notLike NOT LIKE '% 值 %' likeLeft LIKE '% 值' likeRight LIKE '值 %' isNull 字段 IS NULL isNotNull 字段 IS NOT NULL in 字段 IN (value.get(0), value.get(1), ...) notIn 字段 NOT IN (value.get(0), value.get(1), ...) inSql 字段 IN (sql 语句) notInSql 字段 NOT IN (sql 语句) groupBy 分组:GROUP BY 字段, ... orderByAsc ORDER BY 字段, ... ASC orderByDesc 排序:ORDER BY 字段, ... DESC orderBy 排序:ORDER BY 字段, ... having HAVING (sql 语句) or 拼接 OR and AND 嵌套 nested 正常嵌套 不带 AND 或者 OR apply 拼接 sql last 无视优化规则直接拼接到 sql 的最后,多次调用以最后一次为准 有 sql 注入的风险, 请谨慎使用,limit 就只能通过 last 实现 exists 拼接 EXISTS (sql 语句) notExists 拼接 NOT EXISTS (sql 语句)
七、使用示例
1、通过 id 查询
UserPO user1 = userMapper.selectById(3);
2、自定义条件
userMapper.selectOne(Wrappers.<UserPO>lambdaQuery() .eq(UserPO::getId, 5) .like(true, UserPO::getUsername, 4));
3、分页:
需要增加一个配置
@Configuration public class DataBaseConfig {@Bean </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> PaginationInterceptor paginationInterceptor() { PaginationInterceptor page </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PaginationInterceptor(); page.setDialectType(</span>"mysql"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> page; }
}
然后可以直接使用 BaseMapper 的 selectPage 返回分页数据;
IPage<UserPO> user3 = userMapper.selectPage(new Page<UserPO>(), null);
4、更多联表查询需要使用 xml
八、多数据源配置
1、 引用依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>2.5.7</version> </dependency>
2、 配置文件
#多数据源 #设置默认的数据源或者数据源组, 默认值即为 master spring.datasource.dynamic.primary =master #设置严格模式, 默认 false 不启动. 启动后在未匹配到指定数据源时候回抛出异常, 不启动会使用默认数据源. spring.datasource.dynamic.strict=false spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:5711/dba_test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 spring.datasource.dynamic.datasource.master.username=username spring.datasource.dynamic.datasource.master.password=pwd spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.dynamic.datasource.slave_name.url=jdbc:mysql://localhost:5711/dfatp?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.dynamic.datasource.slave_name.username=username
spring.datasource.dynamic.datasource.slave_name.password=pwd
spring.datasource.dynamic.datasource.slave_name.driver-class-name=com.mysql.cj.jdbc.Driver
3、 在 service 使用 @DS 切换数据源
@Service @DS("slave_name")//多数据源数据来源设置 public class UserServiceImpl extends ServiceImpl<UserMapper, UserPO> implements IUserService {}
附:如果启动报错 nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/actuate/health/OrderedHealthAggregator
需添加添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>