spring boot 集成 mybatisplus,druid,mongodb,redis,kfka
创建 Spring boot 项目 IDE:jetbrain idea
第一步:选择 Spring Initializr 和 jdk,点击 Next
第二步:填写 Group 和 Artifact,Java 版本, 点击 Next
第三步:选择项目依赖和 Spring boot 版本,这里依赖先不选择,Spring boot 版本选择 2.6.0
第四步:选择项目地址,点击完成
创建完成的项目结构如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Demo │─ pom.xml └─src ├─main │ ├─java │ │ └─com │ │ └─chenpeng │ │ └─demo │ │ DemoApplication.java │ │ │ └─resources │ application.properties │ └─test └─java └─com └─chenpeng └─demo DemoApplicationTests.java
application.properties
集成 MybatisPlus + MySQL MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
图 2.1 框架结构
代码托管:Gitee | Github
文档:MyBatis-Plus
数据库准备 MySQL 版本:8.0.20
创建数据库 demo
1 CREATE DATABASE `demo` CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci' ;
创建 user 表
1 2 3 4 5 6 7 8 9 10 DROP TABLE IF EXISTS `info_user`;CREATE TABLE `info_user` ( `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, `name` varchar (255 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL , `age` int UNSIGNED NULL DEFAULT NULL , `email` varchar (255 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL , `gmt_create` datetime NULL DEFAULT CURRENT_TIMESTAMP , `gmt_modified` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP , PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic ;
插入测试数据:
1 2 3 4 5 INSERT INTO `info_user`(id, name,age, email) VALUES (1 , 'Jone' , 18 , 'test1@chenpeng.com' );INSERT INTO `info_user`(id, name,age, email) VALUES (2 , 'Jack' , 20 , 'test2@chenpeng.com' );INSERT INTO `info_user`(id, name,age, email) VALUES (3 , 'Tom' , 28 , 'test3@chenpeng.com' );INSERT INTO `info_user`(id, name,age, email) VALUES (4 , 'Sandy' , 21 , 'test4@chenpeng.com' );INSERT INTO `info_user`(id, name,age, email) VALUES (5 , 'Billie' , 25 , 'test5@chenpeng.com' );
添加依赖 引入 Spring Boot Starter 父工程:
1 2 3 4 5 6 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.6.0</version > <relativePath /> </parent >
引入 spring-boot-starter、spring-boot-starter-test、mybatis-plus-boot-starter、MySQL 、jdbc依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-jdbc</artifactId > </dependency > <dependency > <groupId > com.baomidou</groupId > <artifactId > mybatis-plus-boot-starter</artifactId > <version > 3.4.3.4</version > </dependency >
配置 在 application.yml 配置文件中添加 MySQL 数据库的相关配置:
1 2 3 4 5 6 7 8 9 spring: application: name: demo datasource: driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&serverTimezone=Asia/Shanghai username: roote password: chenpeng
创建配置类 MybatisPlusConfig.java,添加 @MapperScan 注解,扫描 Mapper 文件夹:
1 2 3 4 5 6 7 8 9 10 @MapperScan(basePackages = "com.chenpeng.demo.mapper") @Configuration public class MybatisPlusConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource getDataSource () { return DataSourceBuilder.create().build(); } }
编码 编写实体类 User.java
1 2 3 4 5 6 7 public class User { private Long id; private String name; private Integer age; private String email; }
编写Mapper类 UserMapper.java
1 2 public interface UserMapper extends BaseMapper <User > {}
测试 添加测试类,进行功能测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 @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(6, userList.size()); userList.forEach(System.out::println); } }
UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper,所以不填写就是无任何条件
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2021-11-24 21:27:31.275 INFO 26076 --- [ main] com.chenpeng.demo.SampleTest : Started SampleTest in 2.059 seconds (JVM running for 2.909) ----- selectAll method test ------ 2021-11-24 21:27:31.474 INFO 26076 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2021-11-24 21:27:31.603 INFO 26076 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. User{id=1, name='Jone' , age=18, email='test1@chenpeng.com' } User{id=2, name='Jack' , age=20, email='test2@chenpeng.com' } User{id=3, name='Tom' , age=28, email='test3@chenpeng.com' } User{id=4, name='Sandy' , age=21, email='test4@chenpeng.com' } User{id=5, name='Billie' , age=24, email='test5@chenpeng.com' } User{id=6, name='Neo' , age=22, email='tes6@chenpeng.com' } 2021-11-24 21:27:31.680 INFO 26076 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2021-11-24 21:27:31.685 INFO 26076 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. Process finished with exit code 0
从上面的输出可以看出,jdbc 数据源是 com.zaxxer.hikari.HikariDataSource,这是 Spring boot 2.0 开始使用的默认 DataSource,接下来我们使用 alibaba 的DruidDataSource。
配置 DruidDataSource [参考](druid/druid-spring-boot-starter at master · alibaba/druid · GitHub )
Druid Spring Boot Starter 用于帮助你在Spring Boot项目中轻松集成Druid数据库连接池和监控。
加入依赖 1 2 3 4 5 <dependency > <groupId > com.alibaba</groupId > <artifactId > druid-spring-boot-starter</artifactId > <version > 1.2.8</version > </dependency >
配置 在 application.yml 配置文件中添加 Druid 数据库的相关配置:
1 2 3 4 5 6 7 8 9 10 spring: application: name: demo datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&serverTimezone=Asia/Shanghai username: root password: chenpeng
可以看到,添加了 type 属性,jdbc-url 换成了 url
改写配置类 MybatisPlusConfig.java
1 2 3 4 5 6 7 8 9 10 @MapperScan(basePackages = "com.chenpeng.demo.mapper") @Configuration public class MybatisPlusConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource getDataSource () { return DruidDataSourceBuilder.create().build(); } }
编码 其他组件编码不变
测试
使用之前的测试代码进行测试,查看输出
1 2 3 4 5 6 7 8 9 10 11 12 13 ----- selectAll method test ------ 2021-11-24 21:40:27.651 INFO 25904 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited User{id=1, name='Jone' , age=18, email='test1@chenpeng.com' } User{id=2, name='Jack' , age=20, email='test2@chenpeng.com' } User{id=3, name='Tom' , age=28, email='test3@chenpeng.com' } User{id=4, name='Sandy' , age=21, email='test4@chenpeng.com' } User{id=5, name='Billie' , age=24, email='test5@chenpeng.com' } User{id=6, name='Neo' , age=22, email='tes6@chenpeng.com' } 2021-11-24 21:40:27.806 INFO 25904 --- [ionShutdownHook] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} closing ... 2021-11-24 21:40:27.812 INFO 25904 --- [ionShutdownHook] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} closed Process finished with exit code 0
可以看到,数据源已经变为 com.alibaba.druid.pool.DruidDataSource
集成 MongoDB 有一些数据的最佳表现形式是文档(document)。也就是说,不要把这些数据分散到多个表、节点或实体中,将这些信息收集到一个非规范化(也就是文档)的结构中会更有意义。尽管两个或两个以上的文档有可能会彼此产生关联,但是通常来讲,文档是独立的实体。能够按照这种方式优化并处理文档的数据库,我们称之为文档数据库。
例如,假设我们要编写一个应用程序来获取大学生的成绩单,可能需要根据学生的名字来查询其成绩单,或者根据一些通用的属性来查询成绩单。但是,每个学生是相互独立的,任意的两个成绩单之间没有必要相互关联。尽管我们能够使用关系型数据库模式来获取成绩单数据(也许你曾经这样做过),但文档型数据库可能才是更好的方案。
了解文档型数据库能够用于什么场景是很重要的。但是,知道文档型数据库在什么情况下不适用同样也是很重要的。文档数据库不是通用的数据库,它们所擅长解决的是一个很小的问题集。
有些数据具有明显的关联关系,文档型数据库并没有针对存储这样的数据进行优化。例如,社交网络表现了应用中不同的用户之间是如何建立关联的,这种情况就不适合放到文档型数据库中。在文档数据库中存储具有丰富关联关系的数据也并非完全不可能,但这样做的话,你通常会发现遇到的挑战要多于所带来的收益。
MongoDB 是最为流行的开源文档数据库之一。Spring Data MongoDB 提供了三种方式在 Spring 应用中使用 MongoDB:
通过注解实现对象-文档映射;
使用 MongoTemplate 实现基于模板的数据库访问;
自动化的运行时 Repository 生成功能。
在使用这些特性之前,我们首先要配置 Spring Data MongoDB。
配置 MongoDB 第一步:添加依赖
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-mongodb</artifactId > </dependency >
第二步:在 application.yml 添加配置
1 2 3 4 5 spring: data: mongodb: uri: mongodb://chenpeng:chenpeng@localhost:27017/demo
我们不需要配置 MongoClient,因为 Spring boot 的自动配置会为我们生成了客户端,并且生成了一个 MongoTemplate bean,实现基于模板的数据库访问。
编码 编写实体类 Order.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package com.chenpeng.demo.entity;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.mapping.Document;import org.springframework.data.mongodb.core.mapping.Field;@Document(value = "order") public class Order { @Id private String id; @Field("customer1") private String customer; private String type; public Order () { } }
@Document() 标识要持久化到 MongoDB 的域对象。value 属性的值为 MongoDB 中集合名称。如果未配置,默认集合名称将从类型名称派生。
@Id 标识主键。
@Field 注解用于定义文档字段。如果文档字段和类属性名称一致可以省略。
编写 OrderMapper.java,继承自 MongoRespsitory 类,启用 Spring Data MongoDB 的自动化 Repository 生成功能。
1 2 public interface OrderMapper extends MongoRepository <Order , String > {}
编写 OrderService 接口
1 2 3 4 public interface OrderService { <T> T save (T objectToSave) ; List<Order> findAll () ; }
上面我编写了2个方法,第一个方法直接使用 MongoTemplate,第二种方法使用了Spring Data MongoDB 的自动化 Repository 生成功能。具体实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Service public class OrderServiceImpl implements OrderService { private final MongoOperations mongo; private final OrderMapper orderMapper; public OrderServiceImpl (MongoOperations mongo, OrderMapper orderMapper) { this .mongo = mongo; this .orderMapper = orderMapper; } @Override public <T> T save (T objectToSave) { return mongo.save(objectToSave); } @Override public List<Order> findAll () { return orderMapper.findAll(); } }
编写 Controller 方法,来分别测试两种方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @RestController @RequestMapping("/api") public class OrderController { private final OrderService orderService; public OrderController (OrderService orderService) { this .orderService = orderService; } @RequestMapping("/save") public Order saveOrder () { Order order = new Order(); String customer = "Joe" ; String type = "device" ; order.setCustomer(customer); order.setType(type); return orderService.save(order); } @RequestMapping("/getOrder") public List<Order> getList () { return orderService.findAll(); } }
测试 使用 postman 发送请求,查看结果
1 2 3 4 5 { "id" : "619f692f8c8a1b794a87ea71" , "customer" : "Joe" , "type" : "device" }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [ { "id" : "619f435351088848a3ccb2f9" , "customer" : null , "type" : null }, { "id" : "619f441b6cafda1f68413557" , "customer" : "Joe" , "type" : "device" }, { "id" : "619f692f8c8a1b794a87ea71" , "customer" : "Joe" , "type" : "device" } ]
测试结果成功