【编程不良人】Mybatis-Plus整合SpringBoot学习笔记

1. Mybatis-Plus简介

配套视频:【编程不良人】Mybatis-Plus整合SpringBoot实战教程,提高的你开发效率,后端人员必备!_哔哩哔哩_bilibili

官网:MyBatis-Plus

2. MyBatis-Plus环境搭建

配套视频:2.环境搭建&helloworld_哔哩哔哩_bilibili

2.1 创建SpringBoot项目并在pom.xml中引入依赖

 <!--mybatis-plus-->
 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>3.2.0</version>
 </dependency>
 ​
 <!--引入阿里巴巴druid数据库连接池-->
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid</artifactId>
     <version>1.1.19</version>
 </dependency>

       注意:不需要再引入mybatis的相关依赖,只引入mybatis-plus这一个即可,当然数据库相关的驱动还需要显式引入。

2.2 启动类/入口类添加@Mapper注解扫描dao包

 package com.study;
 ​
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 ​
 @SpringBootApplication
 @MapperScan("com.study.dao")//这种方式比@Mapper注解扫描更灵活
 public class SpringbootMybatisplusApplication {
     public static void main(String[] args) {
         SpringApplication.run(SpringbootMybatisplusApplication.class, args);
     }
 }

2.3 application.properties编写mybatis-plus及日志相关配置

 # 配置mybatis-plus,mapper文件位置、实体类别名设置均可省略不写
 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus?characterEncoding=UTF-8
 spring.datasource.username=root
 spring.datasource.password=root
 ​
 # 日志配置
 logging.level.root=info
 logging.level.com.study.dao=debug

2.4 创建数据库及表结构

 DROP TABLE IF EXISTS `user`;
 CREATE TABLE `user` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `name` varchar(255) DEFAULT NULL,
   `age` int(11) DEFAULT NULL,
     `bir` timestamp null default null,
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 ​
 SET FOREIGN_KEY_CHECKS = 1;
 ​
 INSERT INTO `user` VALUES (1,'小崔',27,'2022-08-01');

2.5 开发实体类

  • User.java

 package com.study.entity;
 ​
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.ToString;
 import lombok.experimental.Accessors;
 ​
 import java.util.Date;
 ​
 /**
  * @ClassName User
  * @Description TODO
  * @Author Jiangnan Cui
  * @Date 2022/8/13 23:08
  * @Version 1.0
  */
 @Data //getter、setter
 @AllArgsConstructor //有参构造
 @NoArgsConstructor //无参构造
 @ToString //toString
 @Accessors(chain = true)//开启链式调用
 public class User {
     private String id;
     private String name;
     private Integer age;
     private Date bir;
 }

2.6 开发dao接口(即mapper通用实现,无需再写XxxMapper.xml对应实现)

  • IUserDao.java

 package com.study.dao;
 ​
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.study.entity.User;
 ​
 /**
  * @ClassName IUserDao
  * @Description TODO
  * @Author Jiangnan Cui
  * @Date 2022/8/13 23:12
  * @Version 1.0
  */
 //使用mybatis-plus去增强接口,BaseMapper中提供了各种CRUD方法
 public interface IUserDao extends BaseMapper<User> {
 }
 ​

2.7 测试

  • IUserDaoTest

 package com.study.test;
 ​
 import com.study.dao.IUserDao;
 import com.study.entity.User;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 ​
 import java.util.List;
 ​
 /**
  * @ClassName IUserDaoTest
  * @Description TODO
  * @Author Jiangnan Cui
  * @Date 2022/8/13 23:15
  * @Version 1.0
  */
 @SpringBootTest
 public class IUserDaoTest {
     @Autowired
     private IUserDao userDao;
     /**
      * @MethodName findAllTest
      * @Description 测试查询所有   
      * @Author Jiangnan Cui
      * @Date 23:44 2022/8/13
      */
     @Test
     public void findAllTest(){
         List<User> users = userDao.selectList(null);
         users.forEach(user-> System.out.println("user = " + user));
     }
 }

运行结果:

 2022-08-13 23:30:42.647  INFO 21744 --- [           main] com.study.test.IUserDaoTest              : Started IUserDaoTest in 1.849 seconds (JVM running for 2.58)
 2022-08-13 23:30:42.946  INFO 21744 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
 2022-08-13 23:30:43.105 DEBUG 21744 --- [           main] com.study.dao.IUserDao.selectList        : ==>  Preparing: SELECT id,name,bir,age FROM user 
 2022-08-13 23:30:43.125 DEBUG 21744 --- [           main] com.study.dao.IUserDao.selectList        : ==> Parameters: 
 2022-08-13 23:30:43.147 DEBUG 21744 --- [           main] com.study.dao.IUserDao.selectList        : <==      Total: 1
 user = User(id=1, name=小崔, age=27, bir=Mon Aug 01 00:00:00 CST 2022)

3. 常用注解

配套视频:3.常用的注解_哔哩哔哩_bilibili

注解链接:注解 | MyBatis-Plus

3.1 @TableName注解

 描述: 用来将实体对象与数据库表名完成映射
 ​
 修饰范围: 用在类上
 ​
 常见属性:
     value: String类型,指定映射的表名
     resultMap: String类型,用来指定XML配置中resultMap的id值
 ​
 举例:数据库中表t_user与实体类User
     @Data //getter、setter
     @AllArgsConstructor //有参构造
     @NoArgsConstructor //无参构造
     @ToString //toString
     @Accessors(chain = true)//开启链式调用
     @TableName(value = "t_user") //默认将类名作为表名
     public class User {
         private String id;
         private String name;
         private Integer age;
     }

3.2 @TableId注解

 描述:主键注解
 ​
 修饰范围: 用在属性上
 ​
 常见属性:
     value: String类型,指定实体类中与表中对应的主键列名
     type: 枚举类型,指定主键生成类型
 ​
 举例:id作为自增主键
     @Data //getter、setter
     @AllArgsConstructor //有参构造
     @NoArgsConstructor //无参构造
     @ToString //toString
     @Accessors(chain = true)//开启链式调用
     @TableName(value = "t_user") //默认将类名作为表名
     public class User {
         @TableId(value = "id",type = IdType.AUTO)
         private String id;
         private String name;
         private Integer age;
         private Date bir;
     }

3.3 @TableFileld注解

 描述:字段注解(非主键)
 ​
 修饰范围: 用在属性上
 ​
 常用属性:
     value:  String类型, 用来指定对应的数据库表中的字段名
     el:String类型,映射为原生#{...}逻辑,相当于写在xml里的#{}部分,3.0版本不存在
     exist:boolean类型,是否为数据库表字段 true代表是数据库字段,false代表不是
     
 举例:
     @Data //getter、setter
     @AllArgsConstructor //有参构造
     @NoArgsConstructor //无参构造
     @ToString //toString
     @Accessors(chain = true)//开启链式调用
     @TableName(value = "t_user") //默认将类名作为表名
     public class User {
         
         @TableId(value = "id",type = IdType.AUTO)
         private String id;
 ​
         @TableField(value = "username")//将数据库表中字段与实体类字段进行映射
         private String name;
        
         private Integer age;
         private Date bir;
 ​
         @TableField(exist = false)//不映射数据库表中的任何字段
         private String aaa;
     }
 ​
 补充:
     select:表示是否查询该字段
     fill:表示是否自动填充,将对象存入数据库的时候,由 MyBatis 
     Plus:自动给某些字段赋值,create_time、update_time
 ​
 1、给表添加 create_time、update_time 字段
 ​
 2、实体类中添加成员变量
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 import java.util.Date;
 ​
 @Data
 @TableName(value = "user")
 public class User {
     @TableId
     private String id;
     @TableField(value = "name",select = false)
     private String title;
     private Integer age;
     @TableField(exist = false)
     private String gender;
     @TableField(fill = FieldFill.INSERT)
     private Date createTime;
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Date updateTime;
 }
 ​
 3、创建自动填充处理器
 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
 import org.apache.ibatis.reflection.MetaObject;
 import org.springframework.stereotype.Component;
 import java.util.Date;
 ​
 @Component
 public class MyMetaObjectHandler implements MetaObjectHandler {
     @Override
     public void insertFill(MetaObject metaObject) {
         this.setFieldValByName("createTime",new Date(),metaObject);
         this.setFieldValByName("updateTime",new Date(),metaObject);
     }
 ​
     @Override
     public void updateFill(MetaObject metaObject) {
         this.setFieldValByName("updateTime",new Date(),metaObject);
     }
 }
 ​

其余注解参考:注解 | MyBatis-Plus

也可参考:从前慢- Mybatis-Plus_unique_perfect的博客-CSDN博客_mybatis plus unique

4. 常见方法的使用(CRUD)

配套视频:4.常见方法的使用_哔哩哔哩_bilibili

  • IUserDaoTest.java

 package com.study.test;
 ​
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.study.dao.IUserDao;
 import com.study.entity.User;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 ​
 import java.util.Date;
 import java.util.List;
 ​
 /**
  * @ClassName IUserDaoTest
  * @Description TODO
  * @Author Jiangnan Cui
  * @Date 2022/8/13 23:15
  * @Version 1.0
  */
 @SpringBootTest
 public class IUserDaoTest {
     @Autowired
     private IUserDao userDao;
     /**
      * @MethodName findAllTest
      * @Description 测试查询所有
      * @Author Jiangnan Cui
      * @Date 23:44 2022/8/13
      */
     @Test
     public void findAllTest(){
         List<User> users = userDao.selectList(null);
         users.forEach(user-> System.out.println("user = " + user));
     }
 ​
     /**
      * @MethodName findByIdTest
      * @Description 根据主键id查询一个
      * @Author Jiangnan Cui
      * @Date 0:29 2022/8/14
      */
     @Test
     public void findByIdTest(){
         User user = userDao.selectById(2);
         System.out.println("user = " + user);
     }
     
     /**
      * @MethodName findTest
      * @Description 条件查询  
      * @Author Jiangnan Cui
      * @Date 0:30 2022/8/14
      */
     @Test
     public void findTest(){
         QueryWrapper<User> queryWrapper = new QueryWrapper<>();
         //queryWrapper.eq("age",28);//设置等值查询
         //queryWrapper.lt("age",28);//设置小于查询
         //queryWrapper.gt("age",28);//设置大于查询
         //queryWrapper.ge("age",28);//设置大于等于查询
         queryWrapper.le("age",28);//设置小于等于查询
         List<User> users = userDao.selectList(queryWrapper);
         users.forEach(user -> System.out.println("user = " + user));
     }
 ​
     /**
      * @MethodName findLikeTest
      * @Description 模糊查询
      * @Author Jiangnan Cui
      * @Date 0:43 2022/8/14
      */
     @Test
     public void findLikeTest(){
         QueryWrapper<User> queryWrapper = new QueryWrapper<>();
         //queryWrapper.like("name","崔");//like: %?% 中间包含
         //queryWrapper.likeLeft("name","王");//likeLeft: %? 以xxx结尾
         queryWrapper.likeRight("name","老");//likeRight: ?% 以xxx开头
         List<User> users = userDao.selectList(queryWrapper);
         for (User user : users) {
             System.out.println("user = " + user);
         }
     }
 ​
     /**
      * @MethodName addTest
      * @Description 新增用户
      * @Author Jiangnan Cui
      * @Date 0:57 2022/8/14
      */
     @Test
     public void addTest(){
         User user = new User();
         user.setName("王二小").setAge(18).setBir(new Date());
         userDao.insert(user);
     }
 ​
     /**
      * @MethodName updateByIdTest
      * @Description 基于主键id进行修改
      * @Author Jiangnan Cui
      * @Date 0:58 2022/8/14
      */
     @Test
     public void updateByIdTest(){
         User user = userDao.selectById(3);
         user.setName("大漂亮");
         userDao.updateById(user);
     }
 ​
     /**
      * @MethodName updateBatchTest
      * @Description 批量修改
      * @Author Jiangnan Cui
      * @Date 1:01 2022/8/14
      */
     @Test
     public void updateBatchTest(){
         User user = new User();
         user.setName("大聪明");
         QueryWrapper<User> updateWrapper = new QueryWrapper<>();
         updateWrapper.eq("age",28);//将年龄为28岁的名字修改为大聪明
         userDao.update(user,updateWrapper);
     }
 ​
     /**
      * @MethodName deleteByIdTest
      * @Description 基于主键id进行删除
      * @Author Jiangnan Cui
      * @Date 1:10 2022/8/14
      */
     @Test
     public void deleteByIdTest(){
         userDao.deleteById(6);
     }
 ​
     /**
      * @MethodName deleteTest
      * @Description 基于条件删除
      * @Author Jiangnan Cui
      * @Date 1:11 2022/8/14
      */
     @Test
     public void deleteTest(){
         QueryWrapper<User> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq("age",28);
         userDao.delete(queryWrapper);
     }
     
 }
 ​

5. 分页查询

配套视频:5.分页查询_哔哩哔哩_bilibili

官方参考链接:分页插件 | MyBatis-Plus

5.1 预先配置

注意:

  1. 使用分页查询必须设置mybatis-plus提供的分页插件进行分页结果拦截,才能实现分页效果。

  2. 目前分页查询仅仅支持单表查询,不能在表连接时使用分页插件,表连接时需要在XxxDao接口中写方法,在XxxDaoMapper.xml中写对应实现。

  • MybatisPlusConfig.java

 package com.study.config;
 ​
 import com.baomidou.mybatisplus.annotation.DbType;
 import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
 ​
 /**
  * @ClassName MybatisPlusConfig
  * @Description TODO
  * @Author Jiangnan Cui
  * @Date 2022/8/14 10:23
  * @Version 1.0
  */
 @EnableTransactionManagement //开启事务管理
 @Configuration
 @MapperScan("com.study.dao")//扫描dao接口所在包
 public class MybatisPlusConfig {
     //分页的拦截器对象
     @Bean
     public PaginationInterceptor paginationInterceptor() {
         PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
         return paginationInterceptor;
     }
 }

5.2 无条件分页查询

 /**
  * @MethodName pageTest
  * @Description 无条件分页查询
  * @Author Jiangnan Cui
  * @Date 10:16 2022/8/14
  */
 @Test
 public void pageTest(){
     //参数1:表示当前页数,默认显示第1页   
     //参数2:表示每页显示记录数,默认显示10条
     IPage<User> page = new Page<>(1,2);
     IPage<User> userIPage = userDao.selectPage(page, null);
     long total = userIPage.getTotal();
     System.out.println("总记录数 = " + total);
     for (User record : userIPage.getRecords()) {
         System.out.println("record = " + record);
     }
 }

5.3 有条件分页查询

 /**
  * @MethodName pageConditionTest
  * @Description 有条件查询
  * @Author Jiangnan Cui
  * @Date 10:33 2022/8/14
  */
 @Test
 public void pageConditionTest(){
     //先定义分页条件
     QueryWrapper<User> queryWrapper = new QueryWrapper<>();
     queryWrapper.eq("age",69);
     //再分页显示
     IPage<User> page = new Page<>(1,2);
     IPage<User> userIPage = userDao.selectPage(page, queryWrapper);
     long total = userIPage.getTotal();
     System.out.println("total = " + total);
     userIPage.getRecords().forEach(user-> System.out.println("user = " + user));
 }

6. 多数据源配置实现读写分离

配套视频:6.多数据源配置实现读写分离_哔哩哔哩_bilibili

       为了确保数据库产品的稳定性,很多数据库拥有双机热备功能。 也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器; 第二台数据库服务器,主要进行读的操作。

6.1 pom.xml引入dynamic-datasource-spring-boot-starter依赖

 <!--多数据源依赖dynamic-datasource-->
 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
     <version>3.0.0</version>
 </dependency>

6.2 application.properties配置数据源

 ## 配置mybatis-plus,mapper文件位置、实体类别名设置均可省略不写
 #spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
 #spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 #spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus?characterEncoding=UTF-8
 #spring.datasource.username=root
 #spring.datasource.password=root
 ​
 # 一主一从举例
 # 指定默认数据源
 spring.datasource.primary=master  
 ​
 # 主数据源 master,默认执行增删改操作
 spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driver
 spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/mybatis-plus?characterEncoding=UTF-8
 spring.datasource.dynamic.datasource.master.username=root
 spring.datasource.dynamic.datasource.master.password=root
 ​
 # 从数据源 salve_1,执行查询操作
 spring.datasource.dynamic.datasource.slave_1.driver-class-name=com.mysql.jdbc.Driver
 spring.datasource.dynamic.datasource.slave_1.url=jdbc:mysql://localhost:3306/mybatis-plus-1?characterEncoding=UTF-8
 spring.datasource.dynamic.datasource.slave_1.username=root
 spring.datasource.dynamic.datasource.slave_1.password=root

6.3 创建多个数据库模拟不同的mysql服务

注意:测试时可新建一个名为mybatis-plus-1的数据库,将mybatis-plus中的表复制过去,进行测试。

DS注解

 作用: 用来切换数据源的注解 
 修饰范围: 方法上和类上均可使用,同时存在时方法注解优先于类上注解(局部优先)。
 Value属性: 切换数据源名称

开发业务层

  • IUserService.java

 package com.study.service;
 ​
 import com.study.entity.User;
 ​
 import java.util.List;
 ​
 /**
  * @ClassName IUserService
  * @Description TODO
  * @Author Jiangnan Cui
  * @Date 2022/8/14 10:59
  * @Version 1.0
  */
 public interface IUserService {
     /**
      * @MethodName findAll
      * @Description 查询所有
      * @return: java.util.List<com.study.entity.User>
      * @Author Jiangnan Cui
      * @Date 11:00 2022/8/14
      */
     List<User> findAll();
 ​
     /**
      * @MethodName save
      * @Description 新增用户
      * @param: user
      * @Author Jiangnan Cui
      * @Date 11:00 2022/8/14
      */
     void save(User user);
 }
 ​
  • IUserServiceImpl.java 实现类

 package com.study.service;
 ​
 import com.baomidou.dynamic.datasource.annotation.DS;
 import com.study.dao.IUserDao;
 import com.study.entity.User;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 ​
 import java.util.List;
 ​
 /**
  * @ClassName IUserServiceImpl
  * @Description TODO
  * @Author Jiangnan Cui
  * @Date 2022/8/14 11:01
  * @Version 1.0
  */
 @Service
 @Transactional
 public class IUserServiceImpl implements IUserService{
     @Autowired
     private IUserDao userDao;
 ​
     @Override
     @DS("slave_1") //指定从数据源执行查询操作
     public List<User> findAll() {
         return userDao.selectList(null);
     }
 ​
     @Override //默认主数据源执行增删改操作
     public void save(User user) {
         userDao.insert(user);
     }
 }

测试

  • IUserServiceTest.java

 package com.study.test;
 ​
 import com.study.entity.User;
 import com.study.service.IUserService;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 ​
 import java.util.Date;
 import java.util.List;
 ​
 /**
  * @ClassName IUserServiceTest
  * @Description TODO
  * @Author Jiangnan Cui
  * @Date 2022/8/14 11:04
  * @Version 1.0
  */
 @SpringBootTest
 public class IUserServiceTest {
     @Autowired
     private IUserService userService;
 ​
     /**
      * @MethodName findAllTest
      * @Description 测试查询所有   
      * @Author Jiangnan Cui
      * @Date 11:21 2022/8/14
      */
     @Test
     public void findAllTest(){
         List<User> users = userService.findAll();
         for (User user : users) {
             System.out.println("user = " + user);
         }
     }
 ​
     /**
      * @MethodName saveTest
      * @Description 测试新增用户   
      * @Author Jiangnan Cui
      * @Date 11:21 2022/8/14
      */
     @Test
     public void saveTest(){
         User user = new User();
         user.setName("小灰灰").setAge(5).setBir(new Date());
         userService.save(user);
     }
 }

       通过结果可以发现,从数据源可以执行查询操作,新增用户的数据出现在主数据源,但主从数据未同步,此处还需要配置,后续会逐渐完善,因此此处只是演示主从机工作过程,并不涉及主从同步。

6.4 项目最终结构

​​​​​​​

 

7. 补充

以下摘自:从前慢- Mybatis-Plus_unique_perfect的博客-CSDN博客_mybatis plus unique

7.1 查询方法

 /**
  * @MethodName testSelectBatchIds
  * @Description 根据多个id进行批量查询,返回list查
  * @Author Jiangnan Cui
  * @Date 11:31 2022/8/14
  */
 @Test
 public void testSelectBatchIds(){
     //根据多个id进行批量查询
     List<User> users = userDao.selectBatchIds(Arrays.asList(1, 4, 7));
     users.forEach(user-> System.out.println("user = " + user));
 }
 ​
 /**
  * @MethodName testSelectByMap
  * @Description 按照map进行多条件查询
  * 注意:Map只能做等值判断,逻辑判断需要使用Wrapper来处理
  * @Author Jiangnan Cui
  * @Date 11:38 2022/8/14
  */
 @Test
 public void testSelectByMap(){
     Map<String,Object> map = new HashMap<>();
     map.put("id",4);
     map.put("age",29);
     List<User> users = userDao.selectByMap(map);
     for (User user : users) {
         System.out.println("user = " + user);
     }
 }

7.2 自定义SQL(多表关联查询)

 package com.yao.mybatisplus.entity;
 ​
 import lombok.Data;
 ​
 @Data
 public class ProductVO {
     private Integer category;
     private Integer count;
     private String description;
     private Integer userId;
     private String userName;
 }
 ​
 ​
 package com.yao.mybatisplus.mapper;
 ​
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.southwind.mybatisplus.entity.ProductVO;
 import com.southwind.mybatisplus.entity.User;
 import org.apache.ibatis.annotations.Select;
 ​
 import java.util.List;
 ​
 public interface UserMapper extends BaseMapper<User> {
     @Select("select p.*,u.name userName from product p,user u where p.user_id = u.id and u.id = #{id}")
     List<ProductVO> productList(Integer id);
 }

7.3 执行 SQL 分析打印

 添加依赖
 p6spy 依赖引入
 <dependency>
   <groupId>p6spy</groupId>
   <artifactId>p6spy</artifactId>
   <version>最新版本</version>
 </dependency>
 ​
 application.yml 配置:
 spring:
   datasource:
     driver-class-name: com.p6spy.engine.spy.P6SpyDriver  # com.mysql.cj.jdbc.Driver
     url: jdbc:p6spy:h2:mem:test # 把jdbc改为jdbc:p6spy
     ...
 ​
 spy.properties 配置:
 #3.2.1以上使用
 modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
 #3.2.1以下使用或者不配置
 #modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
 # 自定义日志打印
 logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
 #日志输出到控制台
 appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
 # 使用日志系统记录 sql
 #appender=com.p6spy.engine.spy.appender.Slf4JLogger
 # 设置 p6spy driver 代理
 deregisterdrivers=true
 # 取消JDBC URL前缀
 useprefix=true
 # 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
 excludecategories=info,debug,result,commit,resultset
 # 日期格式
 dateformat=yyyy-MM-dd HH:mm:ss
 # 实际驱动可多个
 #driverlist=org.h2.Driver
 # 是否开启慢SQL记录
 outagedetection=true
 # 慢SQL记录标准 2 秒
 outagedetectioninterval=2

7.4 MyBatisPlus代码自动生成

  • 引入依赖

 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-generator</artifactId>
     <version>3.4.1</version>
 </dependency>
 ​
 <dependency>
     <groupId>org.apache.velocity</groupId>
     <artifactId>velocity-engine-core</artifactId>
     <version>latest-velocity-version</version>
 </dependency>

注意:根据数据表自动生成实体类、Mapper、Service、ServiceImpl、Controller。

MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖。

  • 启动类

 import com.baomidou.mybatisplus.annotation.DbType;
 import com.baomidou.mybatisplus.generator.AutoGenerator;
 import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
 import com.baomidou.mybatisplus.generator.config.GlobalConfig;
 import com.baomidou.mybatisplus.generator.config.PackageConfig;
 import com.baomidou.mybatisplus.generator.config.StrategyConfig;
 import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
 ​
 public class Main {
     public static void main(String[] args) {
         //创建generator对象
         AutoGenerator autoGenerator = new AutoGenerator();
         
         //数据源
         DataSourceConfig dataSourceConfig = new DataSourceConfig();
         dataSourceConfig.setDbType(DbType.MYSQL);
         dataSourceConfig.setUrl("jdbc:mysql://ip:3306/db?useUnicode=true&characterEncoding=UTF-8");
         dataSourceConfig.setUsername("root");
         dataSourceConfig.setPassword("root");
         dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
         autoGenerator.setDataSource(dataSourceConfig);
         
         //全局配置
         GlobalConfig globalConfig = new GlobalConfig();
         globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");
         globalConfig.setOpen(false);
         globalConfig.setAuthor("southwind");  // 作者
         globalConfig.setServiceName("%sService");  
         autoGenerator.setGlobalConfig(globalConfig);
         
         //包信息
         PackageConfig packageConfig = new PackageConfig();
         packageConfig.setParent("com.yao.mybatisplus");
         packageConfig.setModuleName("generator");
         packageConfig.setController("controller");
         packageConfig.setService("service");
         packageConfig.setServiceImpl("service.impl");
         packageConfig.setMapper("mapper");
         packageConfig.setEntity("entity");
         autoGenerator.setPackageInfo(packageConfig);
         
         //配置策略
         StrategyConfig strategyConfig = new StrategyConfig();
         strategyConfig.setEntityLombokModel(true);
         strategyConfig.setNaming(NamingStrategy.underline_to_camel);
         strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
         autoGenerator.setStrategy(strategyConfig);
 ​
         autoGenerator.execute();
     }
 }

7.5 数据安全保护

 密钥加密:
 // 生成 16 位随机 AES 密钥
 String randomKey = AES.generateRandomKey();
 ​
 // 随机密钥加密
 String url = AES.encrypt("jdbc:mysql://ip:3306/db?useUnicode=true&characterEncoding=UTF-8", randomKey);
 String username = AES.encrypt("root", randomKey);
 String password = AES.encrypt("root", randomKey);
 ​
 url: mpw:+url
 username: mpw:+username
 password: mpw:+password
 ​
 // 加密配置 mpw: 开头紧接加密内容( 非数据库配置专用 YML 中其它配置也是可以使用的 )
 spring:
   datasource:
     url: mpw:qRhvCwF4GOqjessEB3G+a5okP+uXXr96wcucn2Pev6Bf1oEMZ1gVpPPhdDmjQqoM
     password: mpw:Hzy5iliJbwDHhjLs1L0j6w==
     username: mpw:Xb+EgsyuYRXw7U7sBJjBpA==
 ​
 ​
 // Jar 启动参数( idea 设置 Program arguments , 服务器可以设置为启动环境变量 )
 java -jar xxxx.jar --mpw.key=randomKey
 ​

完结 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值