简介:java系列技术分享(持续更新中…)
初衷:一起学习、一起进步、坚持不懈
如果文章内容有误与您的想法不一致,欢迎大家在评论区指正
希望这篇文章对你有所帮助,欢迎点赞 收藏 ⭐留言更多文章请点击
官方文档地址 :https://www.baomidou.com/
MyBatis-Plus
(简称 MP)是一个 MyBatis
的增强工具,在 MyBatis 的基础上只做增
强不做改变,为简化开发、提高效率而生。
MybatisPlus可以节省大量时间
,所有的CRUD代码都可以自动化完成
特性
MyBatis:
mybatis
中默认是关闭的。Mybatis Plus:
Mybatis-Plus
中 默认是开启的 ,不需要额外配置。我们将通过一个简单的 Demo 来阐述 MyBatis-Plus 的强大功能
id | name | age | |
---|---|---|---|
1 | Jone | 18 | [email protected] |
2 | Jack | 20 | [email protected] |
3 | Tom | 28 | [email protected] |
4 | Sandy | 21 | [email protected] |
5 | Billie | 24 | [email protected] |
创建表结构
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
新增数据
DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
结果展示
引用spring boot starter 父工程
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.1version>
<relativePath/>
parent>
引入对应依赖这里使用mysql数据库
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.2.11version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
dependencies>
在 application.yml 配置文件中添加 mysql
数据库的相关配置:
spring:
# 数据源配置
datasource:
# 数据库连接信息配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:///test_demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true&autoReconnect=true&failOverReadOnly=false
username: root
password: root
在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:
@SpringBootApplication
@MapperScan("com.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
编写 Mapper 包下的 UserMapper
接口
继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
//@Mapper 没有没配@MapperScan的需添加@Mapper注解
public interface UserMapper extends BaseMapper<User> {
}
@SpringBootTest
public class SampleTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelect() {
System.out.println(("----- selectAll method test ------"));
List<User> userList = userMapper.selectList(null);
Assert.assertEquals(5, userList.size());
userList.forEach(System.out::println);
}
}
UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器
Wrapper
,所以不填写就是无任何条件
mybatis-plus:
configuration:
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
方法非常多
,我简单列出几个,具体请查看官方文档中的接口链接
:接口文档
// 插入一条记录
int insert(T entity);
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
继承BaseMapper接口
public interface UserDao extends BaseMapper<TestUser> {
}
继承IService
接口
public interface UserService extends IService<User> {
}
继承ServiceImpl
实现UserService
接口
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
条件构造文档链接
AbstractWrapper
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
@SpringBootTest
public class TestPlus {
@Autowired
private UserMapper userMapper;
@Test
void testSelectPage(){
Page<User> page = new Page<>(1,2);
Page<User> result = userMapper.selectPage(page, null);
System.out.println("当前页码"+result.getCurrent());
System.out.println("每页数量"+result.getSize());
System.out.println("数据总数"+result.getTotal());
System.out.println("当前页数据"+result.getRecords());
}
}
@Configuration
public class MpConfig {
@Bean
public MybatisPlusInterceptor pageInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
该类继承了 IPage
类,实现了 简单分页模型
如果你要实现自己的分页模型可以继承 Page
类或者实现 IPage 类
属性名 | 类型 | 默认值 | 描述 |
---|---|---|---|
records | List | emptyList | 查询数据列表 |
total | Long | 0 | 查询列表总记录数 |
size | Long | 10 | 每页显示条数,默认 10 |
current | Long | 1 | 当前页 |
orders | List | emptyList | 排序字段信息,允许前端传入的时候,注意 SQL 注入问题,可以使用 SqlInjectionUtils.check(...) 检查文本 |
optimizeCountSql | boolean | true | 自动优化 COUNT SQL 如果遇到 jSqlParser 无法解析情况,设置该参数为 false |
optimizeJoinOfCountSql | boolean | true | 自动优化 COUNT SQL 是否把 join 查询部分移除 |
searchCount | boolean | true | 是否进行 count 查询,如果指向查询到列表不要查询总记录数,设置该参数为 false |
maxLimit | Long | 单页分页条数限制 | |
countId | String | xml 自定义 count 查询的 statementId |
@SpringBootTest
public class TestPlus {
@Autowired
private UserMapper userMapper;
@Test
void testSelectPage(){
//查询年龄大于5岁小于20岁的用户
//构造条件
QueryWrapper<User> qw = new QueryWrapper<>();
qw.lt("age",20);
qw.gt("age",5);
List<User> userList = userMapper.selectList(qw);
System.out.println(userList);
}
}
结果成功 缺点
:字段名容易写错
@SpringBootTest
public class TestPlus {
@Autowired
private UserMapper userMapper;
@Test
void testSelectPage(){
//查询年龄大于5岁小于20岁的用户
//构造条件
QueryWrapper<User> qw = new QueryWrapper<>();
qw.lambda().lt(User::getAge,20).gt(User::getAge,5);
List<User> userList = userMapper.selectList(qw);
System.out.println(userList);
}
}
直接使用LambdaQueryWrapper
(推荐)@SpringBootTest
public class TestPlus {
@Autowired
private UserMapper userMapper;
@Test
void testSelectPage(){
//查询年龄大于5岁小于20岁的用户
//构造条件
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
qw.lt(User::getAge,20).gt(User::getAge,5);
List<User> userList = userMapper.selectList(lqw);
System.out.println(userList);
}
}
由于存在请求参数可能有值或者null的情况,所以要添加判断
@SpringBootTest
public class TestPlus {
@Autowired
private UserMapper userMapper;
@Test
void testSelectNotNull(){
//模拟查询条件
UserDTO userDTO = new UserDTO();
userDTO.setAge(5);
userDTO.setAge2(20);
//构造条件
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
//链式编程,分开也可以
lqw.ge(null!=userDTO.getAge(),User::getAge,userDTO.getAge())
.lt(null!=userDTO.getAge2(),User::getAge,userDTO.getAge2());
List<User> userList = userMapper.selectList(lqw);
System.out.println(userList);
}
}
结果
@SpringBootTest
public class TestPlus {
@Autowired
private UserMapper userMapper;
@Test
void testSelectPortion(){
//构造条件
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
lqw.select(User::getId,User::getName);
List<User> userList = userMapper.selectList(lqw);
System.out.println(userList);
}
}
@SpringBootTest
public class TestPlus {
@Autowired
private UserMapper userMapper;
@Test
void testSelectPortion2(){
//构造条件
QueryWrapper<User> lqw = new QueryWrapper<>();
lqw.select("count(1) num,age");
lqw.groupBy("age");
List<Map<String, Object>> maps = userMapper.selectMaps(lqw);
System.out.println(maps);
}
}
表名注解,标识当前实体类与数据库表的对应关系
@TableName("sys_user")
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 数据库表名 |
schema | String | 否 | “” | schema |
keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值(当全局 tablePrefix 生效时) |
resultMap | String | 否 | “” | xml 中 resultMap 的 id(用于满足特定类型的实体类对象绑定) |
autoResultMap | boolean | 否 | false | 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建与注入) |
excludeProperty | String[] | 否 | {} | 需要排除的属性名 @since 3.3.1 |
设置当前对应数据库表中的字段关系
@TableName("sys_user")
public class User {
@TableId
private Long id;
@TableField("nickname")
private String name;
private Integer age;
private String email;
}
@TableField(exist=false)
private Integer result;
exist:设置属性在数据库表字段中是否存在,默认为true.此属性无法与value合并使用
@TableField(value = "pwd",select = false)
private String password;
select:设置属性是否参与查询,此属性与select()映射配置不冲突
注解属性如下:
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 数据库字段名 |
exist | boolean | 否 | true | 是否为数据库表字段 |
condition | String | 否 | “” | |
update | String | 否 | “” | |
insertStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:NOT_NULL insert into table_a( |
updateStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:IGNORED update table_a set column=#{columnProperty} |
whereStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:NOT_EMPTY where |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自动填充策略 |
select | boolean | 否 | true | 是否进行 select 查询 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 进行处理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC 类型 (该默认值不代表会按照该值生效) |
typeHandler | Class extends TypeHandler> | 否 | UnknownTypeHandler.class | 类型处理器 (该默认值不代表会按照该值生效) |
numericScale | String | 否 | “” | 指定小数点后保留的位数 |
@TableName("sys_user")
public class User {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String name;
private Integer age;
private String email;
}
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 主键字段名 |
type | Enum | 否 | IdType.NONE | 指定主键类型 |
IdType
值 | 描述 |
---|---|
AUTO | 数据库 ID 自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert 前自行 set 主键值 |
ASSIGN_ID | 分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator 的方法nextId (默认实现类为DefaultIdentifierGenerator 雪花算法) |
ASSIGN_UUID | 分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator 的方法nextUUID (默认 default 方法) |
ID_WORKER | 分布式全局唯一 ID 长整型类型(please use ASSIGN_ID ) |
UUID | 32 位 UUID 字符串(please use ASSIGN_UUID ) |
ID_WORKER_STR | 分布式全局唯一 ID 字符串类型(please use ASSIGN_ID ) |
@Data
public class User {
@Version
private Integer version;
}
@Configuration
public class MpConfig {
@Bean
public MybatisPlusInterceptor pageInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//分页插件
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
//乐观锁
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
使用乐观锁在修改前必须先获取对应version字段数据
? 查询出来的version结果
public class User{
@TableLogic(value = "0",delval = "1")
private Integer isDelete;
}
或者配置文件全局配置
mybatis-plus:
global-config:
db-config:
logic-delete-field: isDelete
#逻辑未删除值
logic-not-delete-value: 0
#逻辑已删除值
logic-delete-value: 1
mybatis-plus:
global-config:
db-config:
#id类型
id-type: ASSIGN_ID
#数据库表默认前缀
table-prefix: tb_
本篇持续更新...........