mybatis-puls 入门和进阶

mybatis-plus 入门和进阶

简介

所有的crud的代码都可以自动完成

JAP、tk -mapper、mybatis-plus

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

快速入门

地址:官网地址

使用第三方插件

  1. 导入依赖

    <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-boot-starterartifactId>
            <version>3.4.1version>
        dependency>
    
  2. 写入配置

  3. 编写代码

步骤

  1. 创建数据库 mybatis-plus

  2. 创建表

    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
    
  3. 插入数据

    INSERT INTO user (id, name, age, email) VALUES
    (1, 'Jone', 18, '[email protected]'),
    (2, 'Jack', 20, '[email protected]'),
    (3, 'Tom', 28, '[email protected]'),
    (4, 'Sandy', 21, '[email protected]'),
    (5, 'Billie', 24, '[email protected]');
    
  4. 添加依赖

<dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    <dependency>
        
        <groupId>com.baomidougroupId>
        <artifactId>mybatis-plus-boot-starterartifactId>
<version>3.0.5version>
dependency>
<dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.37version>
dependency>
  1. 连接数据库

    mysql 5 和,mysql8有区别,但是可以先前兼容,但不同版本最好写成不一样的

# mysql5 com.mysql.jdbc.Driver
# mysql8 com.mysql.cj.jdbc.Driver 需要增加时区配置 serverTimezone=GMT%2B8

spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus?useSSL=false&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver


#运行错误
#1、就是mysql版本不能太高
#2、单元测试少包

#配置日志,输出到控制台
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

逻辑代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Lf9T3tq-1607589902913)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1607155042072.png)]

@Repository
public interface UserMapper extends BaseMapper<User> {
     

}

@MapperScan("com.yanghao.mybatis_plus.mapper")
@SpringBootApplication
public class MybatisPlusApplication {
     

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


@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
     
    //对应数据库中主键(uuid、自增id、雪花算法、redis、zookeeper)
    @TableId(type = IdType.ID_WORKER)
    private Long id;//这要用大写的Long
    private String name;
    private Integer age;
    private String email;
}

思考问题?

  1. sql 谁帮我们写? mybatis-plus
  2. 方法都已经写好啦

测试插入

@SpringBootTest
class MybatisPlusApplicationTests {
     

    @Autowired
    private UserMapper userMapper;
//    查询所有
    @Test
    void contextLoads() {
     
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
//   插入
    @Test
    void contextLoads2() {
     
        User user = new User();
        user.setAge(12);
        user.setName("zhangsan");
        user.setEmail("[email protected]");//帮我们自动生成id
        int insert = userMapper.insert(user);
        System.out.println(insert);

    }
        //更新,通过字符串进行拼接,传入的是一个对象
    @Test
    void contextLoads3() {
     
        User user = new User();
        user.setId(0L);
        user.setName("lisi");
        int insert = userMapper.updateById(user);
        System.out.println(user);
        System.out.println(insert);
    }

}

主键自增

//自增,但是数据库必须成设置自增,否则报错
@TableId(type = IdType.AUTO)
    private Long id;//这要用大写的Long
//其他源码解释
public enum IdType {
     
    AUTO(0),//自增
    NONE(1),//未设置
    INPUT(2),//需要手动设置id
    ASSIGN_ID(3),
    ASSIGN_UUID(4)//uuid
        ID_WORKER(3),//默认全局唯一
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5yprtXjC-1607589902917)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1607156182834.png)]

CRUD扩展

时间填充

自动填充

创建时间、修改时间。这些操作自动完成。

数据库界级别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NUwJO3kY-1607589902919)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1607158676929.png)]

代码级别的自动填充时间

//实体类中的配置 
	@TableField(fill = FieldFill.INSERT)//插入的时候起作用
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)//更新和插入的时候都起作用
    private Date updateTime;

//需要配置类中说明
//@Slf4j是用作日志输出的,一般会在项目每个类的开头加入该注解,如果不写下面这段代码,并且想用log
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
     
//    插入时填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
     
        log.info("start insert fill");
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
//更新时填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
     
        log.info("start update fill");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

乐观锁

乐观锁:顾名思义,认为不会出现问题,出了问题,再更新测试

悲观锁:干什么都会上锁。

乐观锁实现方式:

  • 取出记录时,获取版本version

  • 更新时带上这个版本

  • 执行更新时 set version=new version where version =oldversion

  • 如果version不对,就更新失效

    乐观锁 1、先查询,获取版本号 version=1
    A---
    set name='张三' ,version=version+1 where version=1 and id=2
    B---线程强先完成,会导致A更新失败
    set name='李四' ,version=version+1 where version=1
        
        
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TO0fSqVe-1607589902926)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1607232089902.png)]

1、添加字段

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

2、注册组件

@MapperScan("com.yanghao.mybatis_plus.mapper")//可以把启动类中的注解移到这
@EnableTransactionManagement //开启事务
@Configuration//配置类
public class MybatisPlusConfig {
     
    //注册乐观锁组件
    @Bean
    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor(){
     
        return new OptimisticLockerInnerInterceptor();
    }
}

//上面那个拦截器用不了,需要包装一层MybatisPlusInterceptor 
@MapperScan("com.yanghao.mybatis_plus.mapper")//可以把启动类中的注解移到这
@EnableTransactionManagement //开启事务
@Configuration//配置类
public class MybatisPlusConfig {
     
    //注册乐观锁组件
    @Bean
    public MybatisPlusInterceptor optimisticLockerInnerInterceptor() {
     
//        return new OptimisticLockerInnerInterceptor();
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

3、测试

 //测试乐观锁,第一个user没更改成功
    @Test
    void contextLoads4() {
     
        User user = userMapper.selectById(0L);
        user.setName("yanghao");

        //模拟另一个线程插队
        User user2 = userMapper.selectById(0L);
        user2.setName("lihao");
        userMapper.updateById(user2);

        //可以尝试使用自旋锁。
        userMapper.updateById(user);

    }

其他api的使用

    //根据id查询多个用户
    @Test
    void contextLoads5() {
     
//        List users = userMapper.selectList();
        List<User> users = userMapper.selectBatchIds(Arrays.asList(0, 1, 2));
        users.forEach(System.out::println);
    }                                                                                      //按条件查询之一使用map,就是存储的where条件
	 @Test
    void contextLoads6() {
     
        HashMap<String, Object> map = new HashMap<>();
        map.put("name","lihao");
        map.put("age",18);
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }

分页查询

网站分页技术非常多!

  1. 原始limit
  2. pageHelper
  3. MP内置插件

如何使用

  1. 配置拦截器插件即可

    @Bean
        public PaginationInnerInterceptor paginationInnerInterceptor(){
           
            return new PaginationInnerInterceptor();
        }
    //上面这个不好使啦
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
           
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            return interceptor;
        }
    
  2. 直接使用page对象即可

        @Test
        void contextLoads7() {
           
            /**
             * @Param 1 当前页
             * @Param 2 当前页大小
             */
            Page<User> page = new Page<>(1,5);
            Page<User> userPage = userMapper.selectPage(page, null);
            userPage.getRecords().forEach(System.out::println);
            System.out.println(page.getTotal());
        }
    
    

删除操作

@Test
    void contextLoads9() {
     
        int i = userMapper.deleteBatchIds(Arrays.asList(0,1));
    }
//通过map删除,map代表where后面的条件
 @Test
    void contextLoads10() {
     
        HashMap<String, Object> map = new HashMap<>();
        map.put("name","Tom");
        int i = userMapper.deleteByMap(map);
    }

逻辑删除

物理删除:从数据库总删除

逻辑删除:用一个变量表示他删除,其实没删除,类似于垃圾箱。delete

管理员可以查看

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

配置文件

mybatis-plus.global-config.db-config.logic-delete-value=1 #表示逻辑删除
mybatis-plus.global-config.db-config.logic-not-delete-value=0 #表示未删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YywRKYYE-1607589902926)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1607250796786.png)]

//是一个更新操作,并不删除
int i = userMapper.deleteBatchIds(Arrays.asList(2));
#配置开发环境
spring.profiles.active=dev

性能分析插件

作用:拦截慢sql,用于输出每条sql运行时间

  1. 导入插件

    这个性能分析插件早,3.2以上就没有啦
        @Bean
        @Profile({
           "dev", "test"})// 设置 dev test 环境开启
        public PerformanceInterceptor performanceInterceptor() {
           
            return new PerformanceInterceptor();
        }
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.1</version>
    </dependency>
    
  2. 测试使用

 @Test
    void contextLoads() {
     
        // 查询 name 不为空的用户,并且邮箱不为空的用户,年龄大于等于12
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper
                .isNotNull("name")
                .isNotNull("email")
                .ge("age","12");//ge表示大于
        userMapper.selectList(wrapper).forEach(System.out::println);// 和我们学习的 Map 对于以下
    }
@Test
    void contextLoads2() {
     
        // 查询 name 不为空的用户,并且邮箱不为空的用户,年龄大于等于12
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper
                .eq("name","yanghao");//name等于yanghao
        userMapper.selectOne(wrapper).forEach(System.out::println);// 和我们学习的 Map 对于以下
    }
@Test
    void contextLoads13() {
     
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age",20,24);
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
	//左右模糊查询
	@Test
    void contextLoads14() {
     
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper
                .notLike("name","e")
                .likeRight("email","t");
        //Preparing: SELECT id,name,age,email,create_time,update_time,version,deleted 		  //FROM user WHERE deleted=0 AND (name NOT LIKE ? AND email LIKE ?)
		//==> Parameters: %e%(String), t%(String)
        List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
        maps.forEach(System.out::println);
    }
//嵌套查询
    @Test
    void contextLoads15() {
     
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.inSql("id","select id from user where id<5");
        userMapper.selectList(wrapper).forEach(System.out::println);
    }
//排序查询
    @Test
    void contextLoads16() {
     
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");//按id降序查询
        wrapper.orderByAsc("id");//升序排列
        userMapper.selectList(wrapper).forEach(System.out::println);
    }

代码自动生成器

AutoGenerator是mybatis-plus的自动生成器,可以快速生成Entity、Mapper、Mapper.xml、service

等各种模块,提高效率。

        
        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-generatorartifactId>
            <version>${mybatisPlus.version}version>
        dependency>
        <dependency>
            <groupId>org.apache.velocitygroupId>
            <artifactId>velocity-engine-coreartifactId>
            <version>2.0version>
        dependency>
        

自动生成代码

public class GenerateCode {
     
    public static void main(String[] args) {
     
        //构建代码生成器对象
        AutoGenerator generator = new AutoGenerator();
        GlobalConfig gc = new GlobalConfig();//全局配置
        String property = System.getProperty("user.dir");//项目目录
        gc.setOutputDir(property+"/src/main/java");
        gc.setAuthor("yanghao");
        gc.setOpen(false);
        gc.setFileOverride(false);//是否覆盖
        gc.setServiceName("%sService");//去掉Service的I前缀
        gc.setIdType(IdType.ID_WORKER);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true);
        generator.setGlobalConfig(gc);
        //设置数据源
        DataSourceConfig config = new DataSourceConfig();
        config.setUrl("jdbc:mysql://localhost:3306/mybatis-plus?useSSL=false&useUnicode=true&characterEncoding=utf-8");
        config.setUsername("root");
        config.setPassword("root");
        config.setDriverName("com.mysql.jdbc.Driver");
        config.setDbType(DbType.MYSQL);
        generator.setDataSource(config);

        //包的配置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setModuleName("com.yanghao.mybatis_plus");
        packageConfig.setParent("com.yanghao.mybatis_plus");
        packageConfig.setEntity("entity");
        packageConfig.setMapper("mapper");
        packageConfig.setService("service");
        packageConfig.setController("controller");
        generator.setPackageInfo(packageConfig);

        //策略配置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("user");//设置映射的表名
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);//驼峰命名法
        strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
        //strategyConfig.setSuperEntityClass("自己的父类实体,没有就不用设置");
        strategyConfig.setEntityLombokModel(true);
        strategyConfig.setRestControllerStyle(true);
        strategyConfig.setLogicDeleteFieldName("deleted");

        //自动填充配置
        TableFill gmt_createTime = new TableFill("gmt_create", FieldFill.INSERT);
        TableFill gmt_updateTime = new TableFill("gmt_update",FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFill = new ArrayList<>();
        tableFill.add(gmt_createTime);
        tableFill.add(gmt_updateTime);
        strategyConfig.setTableFillList(tableFill);


        //乐观锁配置
        strategyConfig.setVersionFieldName("version");
        strategyConfig.setControllerMappingHyphenStyle(true);
        generator.setStrategy(strategyConfig);

        generator.execute();
    }
}

特此说明:
本文章来自狂神,可以bilibili搜索狂神说

你可能感兴趣的:(java,知识,java,spring)