文章目录
1.MyBatis-plus基础
1.1.mybatis-plus简介
MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
MyBatis-plus官网:https://baomidou.com/
特点:
- 润物无声:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
- 效率至上:只需简单配置,即可快速进行单表 CRUD 操作,从而节省大量时间。
- 丰富功能:代码生成、自动分页、逻辑删除、自动填充等功能一应俱全
1.2.基本使用
- 插入依赖
xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
- 配置文件,这里只配置了数据库,可以加上mybatis-plus加入相关配置,也可以单独创建一个java配置类,专门用于配置mybatis-plus
yml
# DataSource Config
spring:
datasource:
driver-class-name: org.h2.Driver
username: root
password: test
sql:
init:
schema-locations: classpath:db/schema-h2.sql
data-locations: classpath:db/data-h2.sql
- 编写实体类
java
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
- 编写Mapper接口类UserMapper
java
public interface UserMapper extends BaseMapper<User> {
}
要想让spring知道这个bean,有俩种方式
- 在Mapper接口上加上@Mapper注解,自动注入(推荐)
- 在启动类添加@MapperScan扫描注解,扫描Mapper文件夹
1.3.注解映射
上面实例中,实体类名与表名,包括属性名与字段名都是完全一致的,所以mybatis-plus是可以识别的。但在实际开发中,很有可能会出现表名与实体类名不一致,或者属性名与字段名不一致的情况。此时就需要使用注解来进行映射。
● @TableName:表名注解,标识实体类对应的表。
● @TableId:主键注解(可以使用 type=IdType.AUTO 形式指定主键生成策略)
● @TableField:字段注解(非主键)
一般在代码中,实体类应该跟数据库中字段名保持一致,这是规范做法
主键生成策略
主键生成策略类型 | 描述 |
---|---|
AUTO | 数据库 ID 自增 |
INPUT | insert 前自行 set 主键值 |
ASSIGN_ID | 分配 ID(主键类型为 Number(Long 和 Integer)或 String) |
ASSIGN_UUID | 分配 UUID,主键类型为 String |
使用对应策略时,要注意数据库中主键属性与对应策略保持一致,否则无法应用,如果第一次Snowflake生成之后删掉后面应用策略的时候还是生成Snowflake,需要把数据库对应表删除重新建
1.4.命名转换问题
在实际开发中,项目中的类名、属性名,包括数据库中的表名、字段名,这些命名要严格遵守规范。一般来说:
● 在数据库设计中,由于数据库不区分大小写,所以都采用下划线命名法。
● 在java中,类名都采用帕斯卡命名法(大驼峰),属性名都采用驼峰命名法。
在配置文件加入:
yml
# mybatis-plus配置
mybatis-plus:
configuration:
# 驼峰命名
map-underscore-to-camel-case: true
# 日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: auto
可以开启mybatis-plus的驼峰命名
日志可以使运行时控制台打印输出的SQL语句
1.5.关闭命名转换功能
如果数据库中没有采用下划线命名法,那么可以在SpringBoot的application.yml配置文件中关闭此功能:
yml
mybatis-plus:
configuration:
map-underscore-to-camel-case: false
默认开启
2.BaseMapper核心接口
java
/**
* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
*/
public interface BaseMapper<T> extends Mapper<T> {
/**
* 插入一条记录
* @param entity 实体对象
*/
int insert(T entity);
/**
* 根据 ID 删除
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据实体(ID)删除
* @param entity 实体对象
*/
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.COLLECTION) 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.COLLECTION) 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);
}
查看BaseMapper核心接口的源代码,这里详细说明了封装的增删改查方法