Mybatis-plus

Mybatis-plus

快速入门

1、创建数据库:mybatis_plus

2、创建user表

DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id int(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)
);
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');
-- 真实开发中,version(乐观锁)、deleted(逻辑删除)、gmt_create、gmt_modified

3、编写项目,初始化项目!

4、导入依赖

<!-- 数据库驱动 -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- lombok -->
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
</dependency>
<!-- mybatis-plus -->
<!-- mybatis-plus 是自己开发,并非官方的! -->
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>3.0.5</version>
</dependency>

5、连接数据库使用yaml配置文件

#配置数据库
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/netClass?useUnicode=true&amp;characterEncoding=utf-8
    username: root
    password: 123456

6、编写pojo和mapper接口

pojo:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
  private Long id;
  private String name;
  private Integer age;
  private String email;
}

mapper:

// 在对应的Mapper上面继承基本的类 BaseMapper
@Repository // 代表持久层
public interface UserMapper extends BaseMapper<User> {
  // 所有的CRUD操作都已经编写完成了
  // 你不需要像以前的配置一大堆文件了!
}

测试:

@SpringBootTest
class MybatisPlusApplicationTests {
  // 继承了BaseMapper,所有的方法都来自己父类
  // 我们也可以编写自己的扩展方法!
  @Autowired
  private UserMapper userMapper;
  @Test
  void contextLoads() {
    // 参数是一个 Wrapper ,条件构造器,这里我们先不用 null
    // 查询全部用户
    List<User> users = userMapper.selectList(null);
    users.forEach(System.out::println);
 }
}

配置日志

#配置mybatis-plus
mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.itany.myboot.entity
  configuration:
    #驼峰转换
    map-underscore-to-camel-case: true
    cache-enabled: false
    #打印sql
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  #全局配置
  global-config:
    db-config:
      id-type: auto

CRUD

@Test
    public void insertUser(){
        User user = new User();
        user.setName("admin");
        user.setAge(22);
        user.setEmail("2234137445@qq.com");
        userMapper.insert(user);
    }

主键自增

1、实体类字段上 @TableId(type = IdType.AUTO)
2、数据库字段一定要是自增!

更新操作

@Test
    public void updateUser(){
        User user = new User();
        user.setId(1);
        user.setName("admin");
        user.setAge(9999);
        user.setEmail("2234137445@qq.com");
        userMapper.updateById(user);
}

自动填充

创建时间、修改时间!这些个操作一遍都是自动化完成的,我们不希望手动更新!
阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified几乎所有的表都要配置上!而且需
要自动化!

1、数据库级别

在表中新增字段 create_time, update_time

设置默认值CURRENT_TIMESTAMP

并且更新时间设置自动更新

2、代码级别

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
    private String email;
    //字段自动填充
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

编写处理器

package com.itany.plus.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @Projectname: plus
 * @Filename: MyMetaObjectHandler
 * @Author: wyf
 * @Data: 2022/9/27 22:55
 * @Description: TODO
 */
@Slf4j
@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);
    }
}

乐观锁

乐观锁 : 故名思意十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,
再次更新值测试
悲观锁:故名思意十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!

乐观锁实现方式:

  • 取出记录时,获取当前 version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

1、在表中添加version字段,并且默认值为1

2、在实体类添加对应的字段

@Version //乐观锁Version注解
private Integer version;

3、注册组件

在config包中写

使用@Configuration注解表明这是一个配置类

package com.itany.plus.config;

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * @Projectname: plus
 * @Filename: MybatisPlusConfig
 * @Author: wyf
 * @Data: 2022/9/27 23:23
 * @Description: TODO
 */
@Configuration
@EnableTransactionManagement
public class MybatisPlusConfig {
    //注册乐观锁
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}

测试乐观锁成功

@Test
public void test(){
    User user = userMapper.selectById(1);
    user.setName("dream");
    user.setAge(19);
    userMapper.updateById(user);
}

测试乐观锁失败

@Test
public void test02(){
    User user01 = userMapper.selectById(1);
    user01.setName("dream");
    user01.setAge(20);
    // 模拟另外一个线程执行了插队操作
    User user02 = userMapper.selectById(1);
    user02.setName("dream");
    user02.setAge(22);
    userMapper.updateById(user01);
    //下面语句没有执行成功
    userMapper.updateById(user02);// 如果没有乐观锁就会覆盖插队线程的值!
}

查询操作

// 测试查询
@Test
public void testSelectById(){
    User user = userMapper.selectById(1);
    System.out.println(user);
}
// 测试批量查询!
@Test
public void testSelectByBatchId(){
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
    users.forEach(System.out::println);
}
// 按条件查询之一使用map操作
@Test
public void testSelectByBatchIds(){
    HashMap<String, Object> map = new HashMap<>();
    // 自定义要查询
    map.put("name","admin");
    map.put("age",18);
    List<User> users = userMapper.selectByMap(map);
    users.forEach(System.out::println);
}

分页查询

1、原始的 limit 进行分页
2、pageHelper 第三方插件

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.10</version>
</dependency>
PageHelper.startPage(1, 2);
List<User> users = userMapper.selectList(null);
PageInfo<User> pageInfo = new PageInfo<>(users);

3、MP 其实也内置了分页插件!

  • 配置分页插件(在config包里面)
@Configuration
@EnableTransactionManagement
public class MyConfig {
    // 分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}
  • 直接使用page对象
// 测试分页查询
@Test
public void testPage(){
    // 参数一:当前页
    // 参数二:页面大小
    // 使用了分页插件之后,所有的分页操作也变得简单的!
    Page<User> page = new Page<>(1,5);
    userMapper.selectPage(page, null);
    page.getRecords().forEach(System.out::println);
    System.out.println(page.getTotal());
}

自定义的 mapper#method 使用分页

IPage<UserVo> selectPageVo(IPage<?> page, Integer state);
// or (class MyPage extends Ipage<UserVo>{ private Integer state; })
MyPage selectPageVo(MyPage page);
// or
List<UserVo> selectPageVo(IPage<UserVo> page, Integer state);
<select id="selectPageVo" resultType="xxx.xxx.xxx.UserVo">
    SELECT id,name FROM user WHERE state=#{state}
</select>

删除

1、根据id删除记录

// 测试删除
@Test
public void testDeleteById(){
    userMapper.deleteById(2);
}
// 通过id批量删除
@Test
public void testDeleteBatchId(){ 
    userMapper.deleteBatchIds(Arrays.asList(2,3));
}
// 通过map删除
@Test
public void testDeleteMap(){
    HashMap<String, Object> map = new HashMap<>();
    map.put("name","hello");
    userMapper.deleteByMap(map);
}

逻辑删除

物理删除 :从数据库中直接移除
逻辑删除 :再数据库中没有被移除,而是通过一个变量来让他失效! deleted = 0 => deleted = 1

1、在数据表中增加一个 deleted 字段

2、实体类中增加属性

//逻辑删除
@TableLogic
private Integer deleted;

3、配置!

// 逻辑删除组件!
@Bean
public ISqlInjector sqlInjector() { 
    return new LogicSqlInjector();
}
#配置数据库
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/mybatis_plus?useUnicode=true&amp;characterEncoding=utf-8
    username: root
    password: 123456
#配置mybatis-plus
mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.itany.plus.pojo
  configuration:
    #驼峰转换
    map-underscore-to-camel-case: true
    cache-enabled: false
    #打印sql
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  #全局配置
  global-config:
    db-config:
      id-type: auto
      #逻辑删除
      logic-delete-value: 1
      logic-not-delete-value: 0

4、测试一下删除!

记录依旧在数据库,但是值确已经变化了!

// 测试删除
@Test
public void testDeleteById(){
    userMapper.deleteById(2);
}
// 通过id批量删除
@Test
public void testDeleteBatchId(){ 
    userMapper.deleteBatchIds(Arrays.asList(2,3));
}
// 通过map删除
@Test
public void testDeleteMap(){
    HashMap<String, Object> map = new HashMap<>();
    map.put("name","hello");
    userMapper.deleteByMap(map);
}

性能分析插件

作用:我们在开发过程中,会遇到一些慢sql。如果超过这个时间就停止!

1、导入插件

//SQL执行效率插件
    @Bean
    @Profile({"dev","test"})//设置 dev test 环境开启,保证我们的效率
    public PerformanceInterceptor performanceInterceptor(){
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        //在工作中十分常见
        performanceInterceptor.setMaxTime(100);//ms
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }
spring:
 profiles:
    active: dev

2、测试使用

如果超过执行时间就会报错!!!

返回结果:

Time:20 ms - ID:com.itany.plus.mapper.UserMapper.selectList
Execute SQL:
    SELECT
        id,
        name,
        age,
        email,
        create_time,
        update_time,
        version,
        deleted 
    FROM
        user 
    WHERE
        deleted=0

条件构造器

//通过构造wrapper来进行条件添加
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        //这里相当于where条件后的内容
        wrapper.eq("数据库字段名", "值");
        //不等于这个值
        wrapper.ne("数据库字段名", "值");
        //where id = 1
        wrapper.eq("id", user.getId());
        //where num between a and b
        wrapper.between("数据库字段名", "区间一", "区间二");
        //where name like
        wrapper.like("数据库字段名", "值");
        wrapper.groupBy("数据库字段名");
        //还有notin
        wrapper.in("数据库字段名", "包括的值,使用','分割");
        //还有notinSql
        wrapper.inSql("数据库字段名", "sql语句");
        //升序
        wrapper.orderByAsc("数据库字段名");
        //降序
        wrapper.orderByDesc("数据库字段名");
        //大于等于
        wrapper.ge("数据库字段名", "值");
        //大于
        wrapper.gn("数据库字段名", "值");
        //小于等于
        wrapper.le("数据库字段名", "值");
        //小于
        wrapper.ln("数据库字段名", "值");
        //字段名为空
        wrapper.isNull("数据库字段名");
        //拼接limit
    wrapper.orderByDesc("click_number").last("limit 0,10");

代码自动生成器

package com.example.demo;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
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.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;

/**
 * @Projectname: demo
 * @Filename: AutoCode
 * @Author: wyf
 * @Data: 2022/9/28 17:24
 * @Description: 自动生成代码
 */
public class AutoCode {
    public static void main(String[] args) {
        AutoGenerator mpg = new AutoGenerator();

        //1、全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath+"/src/main/java");
        gc.setAuthor("wyf");
        gc.setOpen(false);
        //是否覆盖原来生成的
        gc.setFileOverride(false);
        gc.setServiceName("%sService");
        gc.setIdType(IdType.AUTO);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true);
        mpg.setGlobalConfig(gc);
        //2、设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        mpg.setDataSource(dsc);
        dsc.setUrl("jdbc:mysql://127.0.0.1:3306/mybatis_plus?useUnicode=true&characterEncoding=utf-8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        dsc.setDbType(DbType.MYSQL);

        //3、配置要生成的包
        PackageConfig pcg = new PackageConfig();
        pcg.setModuleName("blog");
        pcg.setParent("com.example");
        pcg.setEntity("entity");
        pcg.setMapper("mapper");
        pcg.setService("service");
        pcg.setController("controller");
        mpg.setPackageInfo(pcg);


        //4、策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("user"); // 设置要映射的表名
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true); // 自动lombok;
        strategy.setLogicDeleteFieldName("deleted");
        // 自动填充配置
        TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
        TableFill updateTime = new TableFill("update_time",FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(createTime);
        tableFills.add(updateTime);
        strategy.setTableFillList(tableFills);
        // 乐观锁
        strategy.setVersionFieldName("version");
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true); //localhost:8080/hello_id_2
        mpg.setStrategy(strategy);

        mpg.execute();
    }
}

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>user
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.1.1</version>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.3.1.tmp</version>
</dependency>
//需要搭配2.4.10版springboot
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

<dependency>
    <groupId>io.swagger</groupId>
    <artifactId>swagger-annotations</artifactId>
    <version>1.5.22</version>
</dependency>

<dependency>
    <groupId>io.swagger</groupId>
    <artifactId>swagger-models</artifactId>
    <version>1.5.22</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

遇到报错

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/veloc

需要在配置文件添加模板引擎

<!-- 模板引擎 -->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.0</version>
</dependency>
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • MyBatis Plus 本文档基于 MyBatis-Plus 官方文档编写,详情请参见 MyBatis-Plus...
    青丶空阅读 2,364评论 3 17
  • 本测试项目涵盖了Mybatis-Plus框架的入门快速构建以及基本的CRUD相关的操作说明。望可以帮助到有相关需求...
    攻城老狮阅读 612评论 0 2
  • MybatisPlus 特性 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑 损耗小:启动即会...
    njitzyd阅读 665评论 0 0
  • Mybatis-Plus(简称MP)是一个Mybatis的增强工具,在Mybatis的基础上只做增强不做改变,为简...
    故里学Java阅读 379评论 0 3
  • 特性 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑 损耗小:启动即会自动注入基本 CURD,...
    hmx阅读 367评论 0 0

友情链接更多精彩内容