1.PlusMybatis的痛点
MyBatis 是一个基于 java 的持久层框架,内部封装了 jdbc极大提高了我们的开发效率。
但是使用 Mybatis 开发也有很多烦人的地方:
1.每个 Dao 接口都需要自己定义一堆增删改查方法。
/**
* @Desc: UserDao 接口
* @Author: 公众号:知否技术
* @date: 下午7:43 2022/5/7
*/
public interface UserDao {
// 获取所有用户信息
List getUserList();
// 根绝 id 获取用户信息
User getUserById(int id);
// 新增用户信息
boolean add(User user);
// 更新用户信息
boolean update(User user);
// 删除用户信息
boolean delete(int id);
}
2.每个 Mapper 文件都需要写一堆
基本的增删改查语句。
3.如果查询的列表需要分页,我们还需要给查询方法封装成分页对象。
你可能会说:Mybatis 还能有痛点?用着多方便!
对于小项目而言,用着确实还行。但是遇到大项目,光 Dao 接口都有几百个,如果还要手动定义一堆增删改查方法和 sql 语句,那也很浪费时间。
那有没有这样一个框架:
1.封装了 Mybatis,自带 CRUD 方法,我们不需要自己定义 CRUD 方法。
2.提供各种查询方法,不需要在 mapper 文件中写一些基础的 sql 语句。
3.封装了分页功能,让分页查询无比丝滑。
有的,MybatisPlus
闪亮登场。
目录
1.Mybatis的痛点
2. 邂逅 MybatisPlus
3. 入门案例
4. 基本增删改查
5. 构造器
6. 通用 Service
7. 常用注解
8. 分页
9. 代码生成器
10. application.yml 配置
11. 完整代码
12. 遇到的坑
官网:
https://baomidou.com/
MybatisPlus 是在 Mybatis 原有功能的基础上进行了封装。它不做改变,而是增强了 Mybatis 的功能。
我们不用写 mappe.xml ,直接调用它的 API 就能完成 CRUD 和各种查询操作。
而且它自带分页插件等一些高级功能,极大地提高了我们的开发效率。
开发环境:
1.新建 SpringBoot 项目
2.引入依赖
com.baomidou
mybatis-plus-boot-starter
3.4.0
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-test
test
3.创建数据库表
user 表:
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '姓名',
`age` int DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1508421137384648706 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
4.实体类
public class User {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
5.修改 application.yml
server:
port: 8082
servlet:
context-path: /mybatisplus_demo
# 数据源配置
spring:
datasource:
username: root
password: 12345678
url: jdbc:mysql://localhost:3306/ssm?allowPublicKeyRetrieval=true&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
6.新建 UserMapper 接口
注:
(1)因为 mybatis 规定:mapper.xml 文件的名字要和接口名字一样,所以很多人习惯将 Dao 接口命名为 xxxMapper
。
(2)BaseMapper 是 MybatisPlus 内置的接口,它包含基本的 CRUD 方法。
7.启动类添加 @MapperScan 注解
8.测试
@SpringBootTest
public class MybatisPlusDemoApplicationTests {
@Resource
private UserMapper userMapper;
@Test
void testMybatisPlus() {
for (int i = 18; i < 20; i++) {
User user = new User("王小波" + i, i);
userMapper.insert(user);
}
}
}
9.总结
我们发现只要继承 MybatisPlus 的BaseMapper,就能完成基本的增删改查操作,非常方便。
1.新增
User user = new User("王小波", 19);
userMapper.insert(user);
2.编辑
根据 id 更新数据
int rows = userMapper.updateById(user);
if(rows>0){
System.out.println("更新成功");
}
3.删除
根据主键删除信息
userMapper.deleteById("152635612");
根据 map 条件删除信息
Map param = new HashMap<>();
param.put("age", 18);
int rows = userMapper.deleteByMap(param);
if (rows > 0) {
System.out.println("删除成功!");
}
根据 id 集合批量删除
List ids = Stream.of(110, 112, 113, 115).collect(Collectors.toList());
int rows = userMapper.deleteBatchIds(ids);
if (rows > 0) {
System.out.println("删除成功!");
}
4.查询
根据 id 查询
User user = userMapper.selectById(152382374);
根据 map 条件查询
Map param = new HashMap<>();
param.put("age", 18);
List userList = userMapper.selectByMap(param);
根据 id 集合批量查询
List ids = Stream.of(110, 112, 113, 115).collect(Collectors.toList());
List userList = userMapper.selectBatchIds(ids);
MybatisPlus 提供了查询构造器和更新构造器用来生成带有 where 条件的 sql 语句。
(1)封装查询条件的构造器:
QueryWrapper
常用查询条件:
等于:eq
QueryWrapper userWrapper = new QueryWrapper<>();
// 查询名字是张三的用户
userWrapper.eq("name","张三");
List userList = userMapper.selectList(userWrapper);
不等于:ne
QueryWrapper userWrapper = new QueryWrapper<>();
userWrapper.ne("name","张三");
// 查询名字不是张三的用户
List userList = userMapper.selectList(userWrapper);
模糊查询:like
QueryWrapper userWrapper = new QueryWrapper<>();
// 模糊查询
userWrapper.like("name","张");
List userList = userMapper.selectList(userWrapper);
降序:orderByDesc
QueryWrapper userWrapper = new QueryWrapper<>();
// 模糊查询并根据 number 倒序
userWrapper.like("name","张").orderByDesc("number");
List userList = userMapper.selectList(userWrapper);
升序:orderByAsc
QueryWrapper userWrapper = new QueryWrapper<>();
// 模糊查询并根据 number 降序
userWrapper.like("name","张").orderByAsc("number");
List userList = userMapper.selectList(userWrapper);
其他常用的条件可以去官网查看相关文档,这里不再过多赘述:
https://baomidou.com/pages/10c804/#in
(2)封装更新条件的构造器:
UpdateWrapper
UpdateWrapper 的 where 条件和 QueryWrapper 的一样,只不过需要 set 值。
UpdateWrapper userWrapper = new UpdateWrapper<>();
userWrapper.set("name","王小波").set("age",22)
.eq("name","张三");
MybatisPlus 中有一个通用的接口 Iservice 和实现类,封装了常用的增删改查等操作。
1.新建 service 和 实现类
UserService
/**
* @Desc:
* @Author: 公众号:知否技术
* @date: 下午9:57 2022/5/11
*/
public interface UserService extends IService {
}
UserServiceImpl
/**
* @Desc:
* @Author: 公众号:知否技术
* @date: 下午9:57 2022/5/11
*/
@Service
public class UserServiceImpl extends ServiceImpl implements UserService {
}
2.测试
我们发现该 IService 接口封装了一些常用的方法,极大地提高了我们的开发效率。
1.@TableId
MybatisPlus 会默认将实体类中的 id 作为主键。
@TableId 表示 id 的生成策略,常用的有两种:
(1) 基于数据库的自增策略
(2) 使用雪花算法策略随机生成 2.@TableName
如果实体类和数据库的表名不一致,可以使用这个注解做映射
例如:
3.@TableField
当表属性和实体类中属性名不一致时,可以使用这个注解做映射:
MybatisPlus 内部封装了分页插件,只用简单配置一下就能实现分页功能。
1.配置类
/**
* @Desc:
* @Author: 公众号:知否技术
* @date: 下午9:31 2022/5/11
*/
@Configuration
@MapperScan("com.zhifou.mapper")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new
PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
2.测试
@Test
void testMybatisPlus() {
int current = 1;
int size = 10;
Page userPage = new Page<>(current, size);
//获取分页数据
List list = userPage.getRecords();
list.forEach(user->{
System.out.println(user);
});
Page page = userMapper.selectPage(userPage, null);
System.out.println("当前页:" + page.getCurrent());
System.out.println("每页条数:" + page.getSize());
System.out.println("总记录数:" + page.getTotal());
System.out.println("总页数:" + page.getPages());
}
MybatisPlus 可以帮助我们自动生成 controller、service、dao、model、mapper.xml 等文件,极大地提高了我们的开发效率。
1.引入依赖
com.baomidou
mybatis-plus-generator
3.5.1
org.freemarker
freemarker
2.代码生成器工具类
public class CodeGenerator {
public static void main(String[] args) {
// 连接数据库
FastAutoGenerator.create("jdbc:mysql://localhost:3306/ssm?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC", "root", "123456")
.globalConfig(builder -> {
builder.author("知否技术") // 设置作者
.fileOverride() // 覆盖已生成文件
// 设置日期时间
.dateType(DateType.ONLY_DATE)
.outputDir("D:\\WorkSpace\\idea\\mybatisplus_demo\\src\\main\\java"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.zhifou") // 设置父包名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D:\\WorkSpace\\idea\\mybatisplus_demo\\src\\main\\resources\\mapper")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("t_user") // 设置需要生成的表名
.addTablePrefix("t_"); // 设置过滤表前
// 新增数据,自动为创建时间赋值
IFill createFill = new Column("created_date", FieldFill.INSERT);
IFill updateFill = new Column("updated_date", FieldFill.UPDATE);
builder.entityBuilder()
// 设置id类型
.idType(IdType.ASSIGN_ID)
// 开启 Lombok
.enableLombok()
// 开启连续设置模式
.enableChainModel()
// 驼峰命名模式
.naming(NamingStrategy.underline_to_camel)
.columnNaming(NamingStrategy.underline_to_camel)
// 自动为创建时间、修改时间赋值
.addTableFills(createFill).addTableFills(updateFill)
// 逻辑删除字段
.logicDeleteColumnName("is_deleted");
// Restful 风格
builder.controllerBuilder().enableRestStyle();
// 去除 Service 前缀的 I
builder.serviceBuilder().formatServiceFileName("%sService");
// mapper 设置
builder.mapperBuilder()
.enableBaseResultMap()
.enableBaseColumnList();
})
// 固定
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
关键点:
(1)配置数据库连接信息。
自动生成代码需要连接数据库
(2)指定输出目录,这里直接设置你项目的目录,到时候不用赋值粘贴了。 (3)设置父包名。 (4)设置表名
然后右键运行,代码就会自动生成。
# MybatisPlus
mybatis-plus:
global-config:
db-config:
column-underline: true # 驼峰形式
logic-delete-field: isDeleted # 全局逻辑删除的实体字段名
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
db-type: mysql
id-type: assign_id # id策略
table-prefix: t_ # 配置表的默认前缀
mapper-locations: classpath*:/mapper/**Mapper.xml # mapper 文件位置
type-aliases-package: com.zhifou.entity # 实体类别名
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志:打印sql 语句
链接: https://pan.baidu.com/s/1nlRjKOWs3ON53Dh1XXLKGw
提取码: 9un7
1.传参为 0 时,查询语句失效。
例如传递的 age 为 0,查询就会失效
原因:判断 int 是否为空只要 !=null 就行了,如果加上 type != '',0 会被转为 null
。
2.MybatisPlus 更新字段为 null 失败
解决办法:
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String name;
该注解会忽略为空的判断