芯が強い人になるESTJ-A

# Mybatis-plus

IT開発 Tags: 无标签 阅读: 342

使用第三方组件

guid:--link

1导入对应依赖

2研究依赖如何配置

3代码如何编写

4提高扩展技术能力

新建数据库,测试用

DROP TABLE IF EXISTS 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)
);

真实开发,version乐观锁,deleted逻辑删除,gmt_create,gmt-modified

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');

导入依赖包

<!-- 数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- mybatis-plus -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

使用mybatis-plus可以节省代码,尽量不要同时导入mybatis和mybatis-plus,因为会有冲突

连接数据库,配置applicaiton.properties

spring.datasource.username=koa2weibo
spring.datasource.password=passMYblog123
spring.datasource.url=jdbc:mysql://rm-uf6t9m0yx22dxrya5no.mysql.rds.aliyuncs.com:3306/koa2weibo?serverTimezone=Asia/Shanghai&useSSL=true&useUnicode=true&characterEncoding=UTF8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# useSSL=true会报错,空了研究下原因
#mysql8.0需要增加时区,否则报错
#mysql8.0

#配置mybatis-plus日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

传统方式:
pojo层--》dao层(连接mybatis层,配置mapper.xml)--》service层--〉controller层

新的开发方式:使用了mybatis-plus之后
pojo层--》mapper接口--〉使用

新方法:

pojo层

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



}

Mapper,UserMapper接口interface

package com.xuwen.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xuwen.pojo.User;
import org.springframework.stereotype.Repository;

//在对应的Mapper上,继承(extends)基本的接口,BaseMapper<泛型>
//@Repository注解,代表是dao层
@Repository
public interface UserMapper extends BaseMapper<User> {
    //所有的CRUD已经编写完成!已经不需要像以前一样,配置一大堆文件了


}

main方法,需要添加注解,去扫描Mapper下面的包,不写报错

@MapperScan("com.xuwen.mapper")
@SpringBootApplication
public class MybatisPlusDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusDemoApplication.class, args);
    }

}

测试一下,先@Autowired注入,Mapper的信息

//测试
@SpringBootTest
class MybatisPlusDemoApplicationTests {
    //注入
    //继承了BaseMapper,所有的方法均来自,父类,我们也可以编写自己的扩展方法
    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        //查询所有用户
        //必传的蚕食是Wrapper,是一个条件构造器,不用先写null
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);

    }

}

截图信息

截屏2021-08-07 19.56.02.jpg

CRUD扩展

insert

    //测试插入
    @Test
    public void testInsert(){
        User user = new User();
        user.setName("文文学java");
        user.setAge(18);
        user.setEmail("betsyxw@gmail.com");
        int result = userMapper.insert(user);
        System.out.println("受影响的行数:"+result);
        System.out.println(user);
    }

主键生成策略,UUID,雪花算法,redis生成,zookeeper生成
分布式系统唯一ID生成方案

snowflask是twitter的分布式ID,结果是一个Long的id,雪花算法id
修改实体类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
//全球唯一,默认id,IdType.ID_WORKER
    @TableId(type = IdType.ID_WORKER)
    private Long id;
    private String name;
    private Integer age;
    private String email;



}

我们需要配置数据库,主键自增,

1实体类上,需要自增@TableId(type = IdType.AUTO)
2数据库要勾选自增。
截屏2021-08-07 20.26.59.jpg

更新

    //测试更新
    @Test
    public void testUpdate(){
        User user = new User();
        user.setId(5L);
        user.setName("世界上没有学不会,只有自己懒");
        //注意,updateById,参数是一个对象
        int i = userMapper.updateById(user);
        System.out.println("受影响的行数"+i);
    }

自动填充

创建时间,修改时间。基本都是数据库自动更新,自动更新!!!
阿里巴巴开发手册,gtm_create,gmt_modified

方式一:数据库级别--推荐使用

数据表中新增字段,gtm_create,gtm_modified(create_time,update_time)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    private Date createTime;
    private Date updateTime;
    
}

方式二:代码级别

乐观锁,悲观锁

乐观锁:十分乐观,觉得不会出现问题,如果出现问题,再次更新值测试,version
悲观锁:十分悲观,干什么都会出问题,干什么都会上锁,再去操作。
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:

取出记录时,获取当前version
更新时,带上这个version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
https://baomidou.com/guide/interceptor-optimistic-locker.html#optimisticlockerinnerinterceptor

A线程
update user set name="kuangshen", version = version+1 
where id = 2 and version =1;
B线程
update user set name= "kuangshen", version = version+1
where id= 2 and version =1;

第一步给数据库,新增version字段

mybatis-plus自带的乐观锁插件

截屏2021-08-07 21.15.37.jpg

第二步:实体类新增字段

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    private Date createTime;
    private Date updateTime;
    @Version
    private Integer version;

}

第三步:注册主键

新增文件夹config,新增一个配置类,MybatisPlusConfig类

@MapperScan("com.xuwen.mapper")//注解,是扫描mapper文件夹!
@EnableTransactionManagement//自动管理事务
@Configuration//配置类!!!注解
public class MyBatisPlusConfig {

    //注册乐观锁插件
    /**
     * 旧版
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }


}

批量查询

    //批量查询
    @Test
    public void testSelectByBatchId(){
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
        users.forEach(System.out::println);

    }

条件map查询


    //条件查询map
    @Test
    public void testSelectByBatchIds(){
        HashMap<String,Object> map = new HashMap<>();
        //自定义要查询的内容
        map.put("name","狂神说java");
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);

    }

分页

支持的数据库
mysql 、mariadb 、oracle 、db2 、h2 、hsql 、sqlite 、postgresql 、sqlserver 、presto 、Gauss 、Firebird

Phoenix 、clickhouse 、Sybase ASE 、 OceanBase 、达梦数据库 、虚谷数据库 、人大金仓数据库 、南大通用数据库

配置分页拦截器
config里面

@MapperScan("com.xuwen.mapper")//注解,是扫描mapper文件夹!
@EnableTransactionManagement//自动管理事务
@Configuration//配置类!!!注解
public class MyBatisPlusConfig {

    //注册乐观锁插件
    /**
     * 旧版
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

    //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}

test分页查询


    //测试分页查询
    @Test
    public void testPage(){
        Page<User> page = new Page<>(1,5);
        userMapper.selectPage(page,null);
        page.getRecords().forEach(System.out::println);
    }

删除操作

逻辑删除

deleted=0
deleted=1
截屏2021-08-07 22.06.31.jpg

需改实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    private Date createTime;
    private Date updateTime;
    @Version
    private Integer version;
    @TableLogic
    private Integer deleted;
    
}

修改config类


@MapperScan("com.xuwen.mapper")//注解,是扫描mapper文件夹!
@EnableTransactionManagement//自动管理事务
@Configuration//配置类!!!注解
public class MyBatisPlusConfig {

    //注册乐观锁插件
    /**
     * 旧版
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

    //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }

    //逻辑删除插件
    @Bean
    public ISqlInjector sqlInjector(){
        return new LogicSqlInjector();
    }
}

配置application.properites

#配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

性能分析插件

applicaiton.properites


#设置开发环境
spring.profiles.active=dev

mybatis.config配置类

    //逻辑删除组件
    public PerformanceInterceptor performanceInterceptor(){
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(100);//sql执行的最大时间,超过这个时间,则不执行
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }

条件查询器Wrapper

截屏2021-08-07 22.26.46.jpg

测试一:复杂条件查询

@SpringBootTest
public class WrapperTest {
    //加载类
    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        //查询,name不为空,邮箱不为空,年龄大于xx岁的用户
        //Wrapper是一个对象
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("name")
                .isNotNull("email")
                .ge("age",12);

        userMapper.selectList(wrapper).forEach(System.out::println);
    }

}

测试二:

    //测试二:
    @Test
    void test2(){
        //查询name=文文学java
        //eq=equals
        //selectOne查询一个数据,如果多个数据请用List或者Map
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name","文文学java");
        System.out.println(userMapper.selectOne(wrapper));
    }

测试三:

    //测试三:
    //between and
    @Test
    void test3(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age",20,30);
        Integer count = userMapper.selectCount(wrapper);
        System.out.println(count);
    }

测试四:

    //测试四:
    //模糊查询
    @Test
    void test4(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //左边,右边,区分,%e,e%
        wrapper.notLike("name","java")
                .likeRight("email","t");

        List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
        maps.forEach(System.out::println);
    }

测试五:

    //测试五
    //内查询,
    @Test
    void test5(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //id在自查询中查出
        wrapper.inSql("id","select id from user where id<=3");
        List<Object> objects = userMapper.selectObjs(wrapper);
        objects.forEach(System.out::println);
    }

测试六

    //测试六
    //order by
    @Test
    void test6(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //通过id降序
        wrapper.orderByDesc("id");
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

代码自动生成器

dao,pojo,service,controller让程序自己写。

添加 代码生成器 依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>

添加 模板引擎 依赖,MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl,用户可以选择自己熟悉的模板引擎,如果都不满足您的要求,可以采用自定义模板引擎。

Velocity(默认):

<dependency>

<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>latest-velocity-version</version>

</dependency>
Freemarker:

<dependency>

<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>latest-freemarker-version</version>

</dependency>
Beetl:

<dependency>

<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>latest-beetl-version</version>

</dependency>
注意!如果您选择了非默认引擎,需要在 AutoGenerator 中 设置模板引擎。

AutoGenerator generator = new AutoGenerator();

// set freemarker engine
generator.setTemplateEngine(new FreemarkerTemplateEngine());

// set beetl engine
generator.setTemplateEngine(new BeetlTemplateEngine());

// set custom engine (reference class is your custom engine class)
generator.setTemplateEngine(new CustomTemplateEngine());

// other config
...

MyBatisPlusConfig配置类

package com.xuwen.config;

import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import org.apache.ibatis.javassist.tools.rmi.AppletServer;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * author:xuwen
 * Created on 2021/8/7
 */

@MapperScan("com.xuwen.mapper")//注解,是扫描mapper文件夹!
@EnableTransactionManagement//自动管理事务
@Configuration//配置类!!!注解
public class MyBatisPlusConfig {

    //注册乐观锁插件
    /**
     * 旧版
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

    //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }

    //逻辑删除插件
    @Bean
    public ISqlInjector sqlInjector(){
        return new LogicSqlInjector();
    }

    //sql执行效率插件
    public PerformanceInterceptor performanceInterceptor(){
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(100);//sql执行的最大时间,超过这个时间,则不执行
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }
}

代码生成器

手工策略,test新建一个类

package com.xuwen;

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;

/**
 * author:xuwen
 * Created on 2021/8/8
 */
//Mybatis-plus代码自动生成器
public class xuwenMybaitsCode {
    public static void main(String[] args) {
        //第一步:构建一个代码生成器 对象
        AutoGenerator mpg = new AutoGenerator();
        //第二步:配置策略
        //1全剧配置-不要倒错包!!com.baomidou.mybatisplus.generator.config.GlobalConfig;
        GlobalConfig gc = new GlobalConfig();
        //获取当前系统目录
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath+"/src/main/java");
        gc.setAuthor("xuwen");
        gc.setOpen(false);
        gc.setFileOverride(false);
        gc.setServiceName("%sService");//去掉Service的I前缀
        gc.setIdType(IdType.ID_WORKER);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true);//swagger开发文档

        mpg.setGlobalConfig(gc);

        //2设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://rm-uf6t9m0yx22dxrya5no.mysql.rds.aliyuncs.com:3306/koa2weibo?serverTimezone=Asia/Shanghai&useSSL=true&useUnicode=true&characterEncoding=UTF8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("koa2weibo");
        dsc.setPassword("passMYblog123");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        //3配置生成包,生成那些包,包放在哪些位置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName("blog");
        pc.setParent("com.xuwen");
        pc.setEntity("pojo");
        pc.setMapper("mapper");
        pc.setController("controller");
        pc.setService("service");
        mpg.setPackageInfo(pc);

        //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 gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
        TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        //add添加上方的策略
        tableFills.add(gmtCreate);
        tableFills.add(gmtModified);
        strategy.setTableFillList(tableFills);

        //乐观锁
        strategy.setVersionFieldName("version");
        //驼峰命名开启
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);//Localhost:8080/hello_id_2
        //把上方所有的策略,扔到mpg里面
        mpg.setStrategy(strategy);
        
        mpg.execute();//执行
    }

}