【web项目 MybatisPlus 01】
为了更加容易掌握MybatisPlus的内容,需要先创建数据库,然后进行实际操作掌握
一、MybatisPlus demo
1、创建数据库
mybatis_plus
2、创建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) );
3、User表insert数据
INSERT INTO user (id, name, age, email)VALUES (1, 'Jone', 18, 'test1@baomidou.com'), (2, 'Jack', 20, 'test2@baomidou.com'), (3, 'Tom', 28, 'test3@baomidou.com'), (4, 'Sandy', 21, 'test4@baomidou.com'), (5, 'Billie', 24, 'test5@baomidou.com');
4、在idea上创建一个springboot项目,需要引入下面的包
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--lombok用来简化实体类-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
5、在idea的application.properties中配置数据库信息
#mysql数据库连接 spring boot 2.0(内置jdbc5驱动) spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://172.16.137.131:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=123456 spring boot 2.1及以上(内置jdbc8驱动) 注意:driver和url的变化 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://172.16.137.131:3306/mybatis_plus?serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=123456
6、编写代码测试mybatisPlus对数据库的操作
//1、springboot启动类 - 在SpringBoot启动类中添加@MapperScan注解,扫描Mapper文件夹 @SpringBootApplication @MapperScan("com.mobvista.demomp.mapper") public class DemompApplication { public static void main(String[] args) { SpringApplication.run(DemompApplication.class, args); } } 备注:@MapperScan("com.mobvista.demomp.mapper") 括号内添加mapper文件包地址 //2、创建entity包,User类 @Data public class User { private Long id; private String name; private Integer age; private String email; } 备注;@Data相当于@Setter和@Getter -->作用是对私有化属性进行get和set方法 //3、创建mapper包,UserMapper接口 @Repository public interface UserMapper extends BaseMapper<User>{ } 备注:UserMapper继承了BaseMapper,<User>泛型指定是User的引用类型,BaseMapper是已经封装好的接口,内部是一些对数据库的增删改查操作 //4、测试UserMapper对数据库的操作 @SpringBootTest class DemompApplicationTests { @Autowired private UserMapper userMapper; @Test public void findAll(){ List<User> users = userMapper.selectList(null); System.out.println(users); } } 备注:@Autowired自动加载创建对象 注意:IDEA在 userMapper 处报错,因为找不到注入的对象,因为类是动态创建的,但是程序可以正确的执行。 为了避免报错,可以在 dao 层 的接口上添加 @Repository 注 通过以上几个简单的步骤,我们就实现了 User 表的 CRUD 功能,甚至连 XML 文件都不用编写!
7、查看sql输出日志
在application.properties中添加
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
二、MybatisPlus-添加和主键策略
1、添加
数据库验证添加的数据
从数据库中可以看到生成的id是一个长的值,这个值是mp(MybatisPlus简称)生成的,叫做主键策略
2、主键策略
2.1、MP默认的主键策略是:ASSIGN_ID(使用了雪花算法) -->常用在bean中
常用的主键策略值
2.2、AUTO自增策略
需要再创建数据表的时候设置主键自增
实体字段中配置
@TableId(type = IdType.AUTO) private Long id;
要想影响所有实体的配置,可以设置全局主键配置
#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto
三、MybatisPlus-修改和自动填充
1、修改
2、自动填充
背景:在项目中经常会遇到一些数据,例如创建时间和更新时间,在插入的时候是需要取当前时间的,为了方便MP可以自动填充完成这些字段的赋值操作。
# 案例演示
2.1、准备工作:
1)数据库修改:在user表中增加两个字段:create_time、update_time (都是datetime类型)
2)实体类修改:User类中增加createTime、updateTime字段
2.2、在实体类要进行自动填充属性添加注解
2.3、实现元对象处理器接口:创建类实现接口,实现接口两个方法,一个方法添加执行,一个方法修饰执行,设置添加什么值
注意:不要忘记添加 @Component 注解
2.4、测试
1)先做添加操作,库内查看createTime和updateTime是否有值
2)在做更新操作,库内查看createTime和updateTime是否有值
四、mybatisPlus乐观锁
为什么要用乐观锁:适用场景: 当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新
乐观锁的实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时,set version = new Version where version = oldVersion
- 如果version不对,就更新失败
# mp实现乐观锁步骤:
1、在表添加字段作为版本号,在表对应实体类添加版本号属性
2、修改user实体类 -->增加version属性并添加@Version注解
3、配置乐观锁插件 -创建配置文件
创建包config,创建MpConfig.java配置类
@Configuration //此注解代表是一个配置类 @MapperScan("com.mobvista.demomp.mapper") public class MpConfig { /** * 乐观锁插件 */ @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } }
备注:此时可以删除主类中的@MapperScan扫描注解
前三步已经就实现了乐观锁的功能,为了更加明显,需要做以下的调整
改进1:在实体类user中version属性前加@TableField(fill = FieldFill.INSERT)注解
改进2:在实现类MyMateObjectHandler中增加this.setFieldValByName("version",1,metaObject); 让默认值为1自动添加
4、测试乐观锁
//测试乐观锁 @Test public void testOptimisticLocker(){ //1.先根据id查询 User user = userMapper.selectById(6); //2. 修改ID=6的数据 user.setName("大大"); userMapper.updateById(user); } //乐观锁的问题经常出现在并发情况下,但是本次没办法演示,所以可以用更新操作来验证,如果每次version都增1,就说明乐观锁已经实现了
此数据已经被修改
五、MybatisPlus的查询操作
1、多个ID的批量查询
//多个ID的批量查询 @Test public void testSelect1(){ //selectBatchIds方法的参数是一个Collection集合,既可以传一个list对象也可以用Arrays工具类传多个ID ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); List<User> users = userMapper.selectBatchIds(list); System.out.println(users); List<User> users1 = userMapper.selectBatchIds(Arrays.asList(1, 2, 3)); System.out.println(users1); }
2、简单的条件查询
//简单条件查询 //此中查询用到的语句是:SELECT id,name,age,email,create_time,update_time,version FROM user WHERE name = ? AND age = ? AND email = ? @Test public void testSelect2(){ HashMap<String, Object> hm = new HashMap<>(); hm.put("name","赵丽颖"); hm.put("age",25); hm.put("email","123@qq.com"); List<User> users = userMapper.selectByMap(hm); System.out.println("========"+users); }
3、分页查询
mp自带分页插件,只要简单的配置即可实现分页功能
实现步骤:
1)配置分页插件:在配置类(MpConfig类)中添加@Bean配置
/** * 分页插件 */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); }
2)编写分页代码
2.1)插入Page对象,传入两个参数
* 当前页
* 每页记录数
2.2)调用mp的方法实现分页
# 测试selectPage分页 -->最终通过page对象获取相关数据
//分页查询 @Test public void testSelectPage(){ //实体类和分页关联 Page<User> page = new Page(1,3); // 调用selectPage方法返回分页对象 Page<User> userPage = userMapper.selectPage(page, null); //返回对象得到分页所有数据 long pages = userPage.getPages(); long current = userPage.getCurrent();//获取当前页 List<User> records = userPage.getRecords();//查询数据集合 long total = userPage.getTotal();//总记录数 boolean hasNext = userPage.hasNext();//下一页 boolean hasPrevious = userPage.hasPrevious();//上一页 System.out.println(pages); System.out.println(current); System.out.println(records); System.out.println(total); System.out.println(hasNext); System.out.println(hasPrevious); }
# 测试selectMapsPage分页 -->当指定了特定查询列时,希望分页结果列表只返回被查询的列,而不是很多null值。测试selectMapPage分页:结果集是Map
//分页查询 --selectMapsPage分页 @Test public void testselectMapsPage(){ Page<Map<String,Object>> page = new Page<>(1,5); Page<Map<String, Object>> mapPage = userMapper.selectMapsPage(page, null); System.out.println("查询数据集合:"+mapPage.getRecords()); System.out.println("查询当前分页的所有数据:"+mapPage.getPages()); System.out.println("获取当前页:"+mapPage.getCurrent()); System.out.println("获取总数:"+mapPage.getTotal()); System.out.println("上一页:"+mapPage.hasPrevious()); System.out.println("下一页:"+mapPage.hasNext()); }
六、mp实现删除和逻辑删除
1、删除
1.1、根据ID删除
1.2、批量删除
1.3、简单条件删除
//删除 @Test public void testDelete(){ int num = userMapper.deleteById(6); System.out.println(num); } //批量删除 @Test public void testDelete2(){ int ids = userMapper.deleteBatchIds(Arrays.asList(4, 3)); System.out.println(ids); } //简单删除 @Test public void testDelete3(){ Map<String,Object> mp = new HashMap<>(); mp.put("name","高圆圆"); mp.put("age",19); int i = userMapper.deleteByMap(mp); System.out.println(i); }
2、逻辑删除
2.1、物理删除和逻辑删除
物理删除:真是删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后再数据库中仍旧能看到此条数据记录
逻辑删除使用场景:可以进行数据恢复,有关联数据,不变删除
2.2、逻辑删除实现流程
2.2.1、数据库修改
添加delete_status字段
ALTER TABLE `user` ADD COLUMN delete_status boolean DEFAULT( FALSE);
2.2.2、实体类user修改
@TableLogic(value = "0",delval = "1") private Integer deleteStatus;
2.2.3、配置(可选)-->如果在实体类中@TableLogic注解后面没有跟值,可配置,有值就可以不配置
application.properties加入以下配置,此为默认值,如果你的默认值和mp默认的一样,该配置可无
#设置逻辑删除--被删除和无删除的值 mybatis-plus.global-config.db-config.logic-delete-value = 2 mybatis-plus.global-config.db-config.logic-not-delete-value = 1
2.2.4、测试
@Test public void testDelete(){ int num = userMapper.deleteById(21); System.out.println(num); }
删除执行的语句:
发现删除时,并不是执行的delete语句,而是update语句,并且查看数据库发现数据并没有被删除,而是delete_status字段的值从0变成了1
注意:被删除前,数据的delete_status字段的值必须是0,才能被选取出来执行逻辑删除
2.2.5、测试逻辑删除后的查询
//查询所有数据 @Test public void testAll(){ List<User> users = userMapper.selectList(null); users.forEach(System.out::println); }
执行结果:
从执行结果打印出来的语句,可以看到只会查出来没有被删除的数据(即:delete_status=0)
七、条件构造器和常用接口
mybaitis-plus为了应对复杂的查询,引入了wapper
wrapper:条件构造抽象类,最顶端父类,AbstractWrapper: 用于查询条件封装,主要是生成sql语句的where条件 QueryWrapper:查询条件封装(常用),UpdateWrapper:Update条件封装
/* * 用mp实现一些复杂查询 - Wrapper * */ // 1、ge(大于等于)、gt(大于)、le(小于等于)、lt(小于)、isNull(为空)、isNotNull(不为空) @Test public void testQuery(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper .isNotNull("name") .ge("age",20) .isNull("create_time"); int num = userMapper.delete(queryWrapper); System.out.println(num); /* * 执行的sql语句: * UPDATE user SET delete_status=1 WHERE delete_status=0 AND (name IS NOT NULL AND age >= ? AND create_time IS NULL) * 从语句可以看出:queryWrapper的几个条件,刚好就是sql语句中的where条件 * */ } //2、eq(等于)、ne(不等于) @Test public void testQuery1(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("name","高圆圆"); // selectOne()返回的是一条实体记录,当出现多条是会报错 User user = userMapper.selectOne(queryWrapper); //只能返回一条记录,多余一条则会返回异常 System.out.println(user); } //3、between,notBetween @Test public void testQuery2(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.between("age",20,25); Integer count = userMapper.selectCount(queryWrapper); System.out.println(count); } //4、like、notlike、likeLeft、likeRight (模糊查询) @Test public void testQuery3(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper .select("name","age") .like("name","丽") .likeRight("email","123"); List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper); System.out.println(maps); } //5、orderBy(排序)、orderByDesc(降序)、orderByAsc(升序) @Test public void testQuery4(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.orderByDesc("id","age"); List<User> users = userMapper.selectList(queryWrapper); System.out.println(users); }
Wrapper的查询方式
SourceURL:file:///Users/mobvista/Desktop/资料/Java培训课程/慧测_测试开发/尚医通--要学习的new/笔记/01-教案/day01 项目介绍与MyBatis Plus.doc
查询方式 |
说明 |
setSqlSelect |
设置 SELECT 查询字段 |
where |
WHERE 语句,拼接 + WHERE 条件 |
and |
AND 语句,拼接 + AND 字段=值 |
andNew |
AND 语句,拼接 + AND (字段=值) |
or |
OR 语句,拼接 + OR 字段=值 |
orNew |
OR 语句,拼接 + OR (字段=值) |
eq |
等于= |
allEq |
基于 map 内容等于= |
ne |
不等于<> |
gt |
大于> |
ge |
大于等于>= |
lt |
小于< |
le |
小于等于<= |
like |
模糊查询 LIKE |
notLike |
模糊查询 NOT LIKE |
in |
IN 查询 |
notIn |
NOT IN 查询 |
isNull |
NULL 值查询 |
isNotNull |
IS NOT NULL |
groupBy |
分组 GROUP BY |
having |
HAVING 关键词 |
orderBy |
排序 ORDER BY |
orderAsc |
ASC 排序 ORDER BY |
orderDesc |
DESC 排序 ORDER BY |
exists |
EXISTS 条件语句 |
notExists |
NOT EXISTS 条件语句 |
between |
BETWEEN 条件语句 |
notBetween |
NOT BETWEEN 条件语句 |
addFilter |
自由拼接 SQL |
last |
拼接在最后,例如:last(“LIMIT 1”) |