当前位置:   article > 正文

SSM框架学习——MyBatis Plus_java ssm框架实现聚合函数

java ssm框架实现聚合函数

her~~llo,我是你们的好朋友Lyle,是名梦想成为计算机大佬的男人!

博客是为了记录自我的学习历程,加强记忆方便复习,如有不足之处还望多多包涵!非常欢迎大家的批评指正。

今天开始学习MyBatis Plus。主要有以下内容。

  • MyBatisPlus简介
  • 标准数据层开发
  • DQL控制
  • DML控制
  • 快速开发

我们开始吧。

目录

一、MyBatisPlus简介

二、MyBatisPlus入门案例

三、标准数据层开发

标准数据层CRUD功能

Lombok

分页功能

开启日志(application.yml中)

四、DQL编程控制

条件查询

查询方式

查询关系

处理null值

查询投影

查询条件设定

字段映射与表名映射

五、DML编程控制

id生成策略控制

多记录操作

逻辑删除

逻辑删除案例

乐观锁

乐观锁案例

六、代码生成器


一、MyBatisPlus简介

MyBatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率。

官网: 

MyBatis-Plus (baomidou.com)https://baomidou.com/

特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

二、MyBatisPlus入门案例

①创建新模块,选择Spring初始化,并配置模块相关基础信息

②选择当前模块需要使用的技术集(仅保留JDBC)

 ③手动添加MP起步依赖

  1. <dependency>
  2. <groupId>com.baomidou</groupId>
  3. <artifactId>mybatis-plus-boot-starter</artifactId>
  4. <version>3.5.2</version>
  5. </dependency>

④设置jdbc参数(application.yml)

  1. spring:
  2. datasource:
  3. driver-class-name: com.mysql.cj.jdbc.Driver
  4. url: jdbc:mysql://localhost:3306/brand?useSSL=false
  5. username: root
  6. password: 123456
  7. type: com.alibaba.druid.pool.DruidDataSource

⑤制作实体类与表结构(类名与表名对应,属性名与字段名对应)

⑥定义数据接口,继承BaseMapper<User>

  1. @Mapper
  2. public interface BookDao extends BaseMapper<Book> {
  3. }

⑦测试类中注入dao接口,测试功能

  1. @SpringBootTest
  2. class MybatisPlus01QuickstartApplicationTests {
  3. @Autowired
  4. private BookDao bookDao;
  5. @Test
  6. void testGetAll() {
  7. List<Book> books = bookDao.selectList(null);
  8. books.forEach(System.out::println);
  9. }
  10. }

注意事项:

  • 由于MP并未被收录到idea的系统内置配置,无法直接选择加入
  • 如果使用Druid数据源,需要导入对应坐标

三、标准数据层开发

标准数据层CRUD功能

  1. @Test
  2. void testSelectById(){
  3. System.out.println(bookDao.selectById(1));
  4. }
  5. @Test
  6. void testSave(){
  7. Book book = new Book();
  8. book.setName("从你的全世界路过");
  9. book.setPrice(100.00);
  10. book.setType("言情");
  11. bookDao.insert(book);
  12. }
  13. @Test
  14. void testDelete(){
  15. List<Integer> integerList = new ArrayList<Integer>();
  16. integerList.add(12);
  17. integerList.add(13);
  18. bookDao.deleteBatchIds(integerList);
  19. }
  20. @Test
  21. void testUpdate(){
  22. Book book = new Book();
  23. book.setId(9);
  24. book.setPrice(50.00);
  25. bookDao.updateById(book);
  26. }

Lombok

Lombok,一个Java类库,提供了一组注解,简化POJ0实体类开发。

  1. <dependency>
  2. <groupId>org.projectlombok</groupId>
  3. <artifactId>lombok</artifactId>
  4. <version>1.18.24</version>
  5. <scope>provided</scope>
  6. </dependency>
  1. @Data //功能包含下面的注解
  2. //@Setter
  3. //@Getter
  4. //@ToString
  5. //@NoArgsConstructor
  6. //@AllArgsConstructor
  7. //@EqualsAndHashCode
  8. public class Book {
  9. private String name;
  10. private Double price;
  11. private Integer id;
  12. private String type;
  13. }

常用注解:@Data
为当前实体类在编译期设置对应的get/set方法,无参/有参构造方法,toString方法,hashCode方法,equals方法等。

分页功能

①设置分页拦截器作为Spring管理的bean

  1. @Configuration
  2. public class MpConfig {
  3. @Bean
  4. public MybatisPlusInterceptor mybatisPlusInterceptor(){
  5. //定义MP拦截器
  6. MybatisPlusInterceptor mybatisPlusInterceptor =new MybatisPlusInterceptor();
  7. //添加具体的拦截器
  8. mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
  9. return mybatisPlusInterceptor;
  10. }
  11. }

②执行分页查询

  1. @Test
  2. void testGetByPage(){
  3. IPage page = new Page(1,5);
  4. bookDao.selectPage(page,null);
  5. System.out.println("当前页码值:"+page.getCurrent());
  6. System.out.println("每页显示书:"+page.getSize());
  7. System.out.println("一共多少页:"+page.getPages());
  8. System.out.println("一共多少条数据:"+page.getTotal());
  9. System.out.println("当前页数据:"+page.getRecords());
  10. }

开启日志(application.yml中)

  1. #开启MP的日志输出
  2. mybatis-plus:
  3. configuration:
  4. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

四、DQL编程控制

条件查询

MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合

查询方式

查询格式一:常规格式

  1. QueryWrapper queryWrapper=new QueryWrapper();
  2. queryWrapper.lt("price",60);
  3. queryWrapper.gt("price",20);
  4. List<Book> books = bookDao.selectList(queryWrapper);
  5. books.forEach(System.out::println);

查询格式二:lambda格式

  1. QueryWrapper<Book> queryWrapper=new QueryWrapper<Book>();
  2. queryWrapper.lambda().lt(Book::getPrice,50);
  3. List<Book> books1 = bookDao.selectList(queryWrapper);
  4. books1.forEach(System.out::println);

查询格式三:lambda格式

  1. LambdaQueryWrapper<Book> lambdaQueryWrapper = new LambdaQueryWrapper<Book>();
  2. //价格大于20小于50
  3. lambdaQueryWrapper.gt(Book::getPrice,20);
  4. lambdaQueryWrapper.lt(Book::getPrice,50);
  5. //价格小于40或者大于50
  6. lambdaQueryWrapper.gt(Book::getPrice,50).or().lt(Book::getPrice,40);
  7. List<Book> books2 = bookDao.selectList(lambdaQueryWrapper);
  8. books2.forEach(System.out::println);

都支持链式编程。

  1. QueryWrapper queryWrapper=new QueryWrapper();
  2. queryWrapper.lt("price",60).gt("price",20);
  3. List<Book> books = bookDao.selectList(queryWrapper);
  4. books.forEach(System.out::println);

查询关系

并且(and)连着写就可以。

或者(or)在中间加个or()。

  1. lambdaQueryWrapper.gt(Book::getPrice,50);
  2. lambdaQueryWrapper.or();
  3. lambdaQueryWrapper.lt(Book::getPrice,40);

处理null值

if条件控制(不推荐),就是在当前代码行前加if语句。

推荐使用:条件参数控制(条件为true,连接当前条件,否则不连接)。

lambdaQueryWrapper.gt(null!=book.getPrice(),Book::getPrice,20);

查询投影

查询结果包含模型类中部分属性

  1. //查询投影(lambda格式)
  2. LambdaQueryWrapper<Book> lambdaQueryWrapper = new LambdaQueryWrapper<Book>();
  3. lambdaQueryWrapper.select(Book::getPrice,Book::getId);
  4. List<Book> books1 = bookDao.selectList(lambdaQueryWrapper);
  5. books1.forEach(System.out::println);

查询结果包含模型类中未定义的属性(比如查询总共多少条数据)

  1. QueryWrapper<Book> queryWrapper = new QueryWrapper<Book>();
  2. queryWrapper.select("count(*) as count,type");
  3. queryWrapper.groupBy("type");
  4. List<Map<String, Object>> maps = bookDao.selectMaps(queryWrapper);
  5. maps.forEach(System.out::println);

查询条件设定

等号匹配eq

  1. LambdaQueryWrapper<Book> lambdaQueryWrapper = new LambdaQueryWrapper<Book>();
  2. lambdaQueryWrapper.eq(Book::getName,"我是神").eq(Book::getType,"玄幻");
  3. Book book = bookDao.selectOne(lambdaQueryWrapper);
  4. System.out.println(book);

范围查询 lt le gt ge eq between
       

  1. //范围查询 lt le gt ge eq between
  2. LambdaQueryWrapper<Book> lambdaQueryWrapper = new LambdaQueryWrapper<Book>();
  3. lambdaQueryWrapper.between(Book::getPrice,40,60);
  4. List<Book> bookList = bookDao.selectList(lambdaQueryWrapper);
  5. bookList.forEach(System.out::println);

模糊匹配

  1. //模糊匹配
  2. LambdaQueryWrapper<Book> lambdaQueryWrapper = new LambdaQueryWrapper<Book>();
  3. lambdaQueryWrapper.like(Book::getName,"我");
  4. lambdaQueryWrapper.likeLeft(Book::getName,"我");
  5. lambdaQueryWrapper.likeRight(Book::getName,"我");
  6. List<Book> bookList = bookDao.selectList(lambdaQueryWrapper);
  7. bookList.forEach(System.out::println);

分组查询聚合函数

  1. QueryWrapper<Book> queryWrapper = new QueryWrapper<Book>();
  2. queryWrapper.select("count(*) as count,type");
  3. queryWrapper.groupBy("type");
  4. List<Map<String, Object>> maps = bookDao.selectMaps(queryWrapper);
  5. maps.forEach(System.out::println);

其他条件查询可以自行搜索学习。

字段映射与表名映射

问题一:表字段与编码属性设计不同步

问题二:编码中添加了数据库中未定义的属性

问题三:采用默认查询开放了更多的字段查看权限

问题四:表名与编码开发设计不同步

名称:@TableField

类型:属性注解
位置:模型类属性定义上方
作用:设置当前属性对应的数据库表中的字段关系
相关属性:

  • value (默认):设置数据库表字段名称
  • exist:设置属性在数据库表字段中是否存在,默认为true。此属性无法与value合并使用
  • select:设置属性是否参与查询,此属性与select()映射配置不冲突

 
名称:@TableName
类型:类注解
位置:模型类定义上方
作用:设置当前类对应与数据库表关系
相关属性

  • value:设置数据库表名称

五、DML编程控制

id生成策略控制

  1. public class Book {
  2. @TableId(type = IdType.AUTO)
  3. private Integer id;
  4. }

名称:@TableId

类型:属性注解
位置:模型类中用于表示主键的属性定义上方

作用:设置当前类中主键属性的生成策略
相关属性

  • value:设置数据库主键名称
  • type:设置主键属性的生成策略,值参照IdType枚举值

IdType枚举值:

  • AUTO(0)︰使用数据库id自增策略控制id生成
  • NONE(1)︰不设置id生成策略
  • INPUT(2):用户手工输入id
  • ASSIGN_ID(3)︰雪花算法生成id(可兼容数值型与字符串型)
  • ASSIGN_UUID(4):以UUID生成算法作为id生成策略

对雪花算法以及UUID生成算法感兴趣的小伙伴请自行查看学习。

还可以在application.yml中进行id生成策略以及表名前缀的全局设定(好用):

  1. mybatis-plus:
  2. global-config:
  3. db-config:
  4. #id生成策略
  5. id-type: auto
  6. #表名前缀
  7. table-prefix: tb_

多记录操作

按照主键删除多条记录

  1. List<Integer> integerList = new ArrayList<Integer>();
  2. integerList.add(1);
  3. integerList.add(2);
  4. bookDao.deleteBatchIds(integerList);

根据主键查询多条记录

  1. List<Integer> integerList = new ArrayList<Integer>();
  2. integerList.add(1);
  3. integerList.add(2);
  4. bookDao.selectBatchIds(integerList);

逻辑删除

删除操作业务问题:删除某些记录时,相关的业务数据从数据库中丢弃,而不应该被丢弃。

逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中

逻辑删除案例

①数据库表中添加逻辑删除标记字段

(可选)②实体类中添加对应字段,并设定当前字段为逻辑删除标记字段

  1. public class Book {
  2. @TableLogic(value = "0",delval = "1")
  3. private Integer deleted;
  4. }

(可选,推荐)③配置逻辑删除字段值

  1. mybatis-plus:
  2. global-config:
  3. db-config:
  4. logic-delete-field: deleted
  5. logic-not-delete-value: 0
  6. logic-delete-value: 1

底层实现其实还是update。

乐观锁

业务并发现象带来的问题:秒杀

乐观锁案例

①数据库表中添加锁标记字段

 

②实体类中添加对应字段,并设定当前字段为逻辑删除标记字段

  1. public class Book {
  2. @Version
  3. private Integer version;
  4. }

③配置乐观锁拦截器实现锁机制对应的动态SQL语句拼装

  1. @Configuration
  2. public class MpConfig {
  3. @Bean
  4. public MybatisPlusInterceptor mybatisPlusInterceptor(){
  5. //定义MP拦截器
  6. MybatisPlusInterceptor mybatisPlusInterceptor =new MybatisPlusInterceptor();
  7. //添加乐观锁拦截器
  8. mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
  9. return mybatisPlusInterceptor;
  10. }
  11. }

④使用乐观锁机制在修改前必须先获取到对应数据的verion方可正常进行

  1. @Test
  2. void testUpdate(){
  3. Book book1 = bookDao.selectById(5);
  4. Book book2 = bookDao.selectById(5);
  5. book2.setName("NININIaaa");
  6. bookDao.updateById(book2);
  7. book1.setName("NININIbbb");
  8. bookDao.updateById(book1);
  9. }

六、代码生成器

模板:MyBatisPlus提供
数据库相关配置:读取数据库获取信息

开发者自定义配置: 手工配置

①导入坐标

  1. <!--代码生成器-->
  2. <dependency>
  3. <groupId>com.baomidou</groupId>
  4. <artifactId>mybatis-plus-generator</artifactId>
  5. <version>3.4.0</version>
  6. </dependency>
  7. <!--velocity模板引擎-->
  8. <dependency>
  9. <groupId>org.apache.velocity</groupId>
  10. <artifactId>velocity-engine-core</artifactId>
  11. <version>2.3</version>
  12. </dependency>

②//创建代码生成器对象,进行配置,执行生成代码操作

  1. public class Generator {
  2. public static void main(String[] args) {
  3. //为AutoGenerator添加dataSource,读取数据库
  4. AutoGenerator autoGenerator = new AutoGenerator();
  5. DataSourceConfig dataSource = new DataSourceConfig();
  6. dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
  7. dataSource.setUrl("jdbc:mysql://localhost:3306/brand?serverTimezone=UTC");
  8. dataSource.setUsername("root");
  9. dataSource.setPassword("123456");
  10. autoGenerator.setDataSource(dataSource);
  11. //设置全局配置
  12. GlobalConfig globalConfig = new GlobalConfig();
  13. globalConfig.setOutputDir(System.getProperty("user.dir")+"/MybatisPlus_01_quickstart/src/main/java");//设置生成代码的目录
  14. globalConfig.setOpen(true); //设置生成完毕是否打开生成代码所在目录
  15. globalConfig.setAuthor("ylm");//设置作者名
  16. globalConfig.setFileOverride(true);//设置是否覆盖原始生成的文件
  17. globalConfig.setMapperName("%sDao");//设置数据层接口名,%s为占位符,指模块名称
  18. globalConfig.setIdType(IdType.ASSIGN_ID);
  19. autoGenerator.setGlobalConfig(globalConfig);
  20. //设置包名相关配置
  21. PackageConfig packageConfig =new PackageConfig();
  22. packageConfig.setParent("com.aaa");//设置父类包名
  23. packageConfig.setEntity("domain");//设置实体类包名
  24. packageConfig.setMapper("dao");//设置数据层包名
  25. autoGenerator.setPackageInfo(packageConfig);
  26. //策略设置
  27. StrategyConfig strategyConfig = new StrategyConfig();
  28. strategyConfig.setInclude("tb_book");//设置哪些表生成
  29. strategyConfig.setTablePrefix("tb_");//告诉它前缀是什么,生成实体类就不带前缀了
  30. strategyConfig.setRestControllerStyle(true);//是否启用REST风格
  31. strategyConfig.setVersionFieldName("version");//设置乐观锁字段
  32. strategyConfig.setLogicDeleteFieldName("deleted");//设置逻辑删除字段
  33. strategyConfig.setEntityLombokModel(true);//设置是否启用lombok
  34. autoGenerator.setStrategy(strategyConfig);
  35. //执行代码生成操作
  36. autoGenerator.execute();
  37. }
  38. }

补充,MP还提供了IService<Book>来简化业务层的开发,同数据层类似,但是一半不用,因为业务层需要添加别的代码。有应用可以用。

结语:

SSM框架学习大致就到此结束了,复习复习就开始下一阶段咯。冲!

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号