Mybatis-Plus(Oracle)学习笔记

数据库使用的是Oracle,非Mysql

Mybatis-Plus简介

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

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 操作智能分析阻断,也可自定义拦截规则,预防误操作

Mybatis-Plus快速入门

  1. 创建数据库表并往表里插入数据

mysql:

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)
);
DELETE FROM user;

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

oracle:

--创建user表
CREATE TABLE "user"
(
  "id" INT NOT NULL,
  "name" VARCHAR2(30) DEFAULT 'user_name' NOT NULL,
  age INT DEFAULT 0 NOT NULL,
  email VARCHAR2(50) DEFAULT NULL,
	PRIMARY KEY ("id")
);
--给表的每个字段添加注释
comment on column "user"."id" is '主键id';
comment on column "user"."name" is '姓名';
comment on column "user".age is '年龄';
comment on column "user".email is '邮箱';
select * from user_col_comments where TABLE_NAME='user';
--删除表记录
DELETE FROM "user";
--往user表添加数据
INSERT ALL
INTO "user" ("id","name", age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com')
INTO "user" ("id","name", age, email) VALUES
(2, 'Jack', 20, 'test2@baomidou.com')
INTO "user" ("id","name", age, email) VALUES
(3, 'Tom', 28, 'test3@baomidou.com')
INTO "user" ("id","name", age, email) VALUES
(4, 'Sandy', 21, 'test4@baomidou.com')
INTO "user" ("id","name", age, email) VALUES
(5, 'Billie', 24, 'test5@baomidou.com')
 SELECT 1 FROM DUAL;
 --提交
 COMMIT;
  1. 创建springboot工程,导入mybatis-plus依赖,尽量不要与mybatis依赖一起导入
 <!--mybatis-plus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc6 -->
        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.4</version>
        </dependency>
  1. 配置yaml配置文件
spring:
#  oracle配置
  datasource:
    username: MYBATIS-PLUS
    password: Wzl7373520
    url: jdbc:oracle:thin:@127.0.0.1:1521:ORCL
    driver-class-name: oracle.jdbc.driver.OracleDriver
  1. 创建一个user实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
  1. 创建一个Mapper接口类
@Repository
public interface UserMapper extends BaseMapper<User> {

}
  1. 在springboot启动类中添加@MapperScan注解,扫描Mapper文件夹
@SpringBootApplication
@MapperScan("com.wuzenglin.mapper")
public class SpringbootMybatisplusApplication {

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

}
  1. 测试
@SpringBootTest
class SpringbootMybatisplusApplicationTests {
    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        List<User> userList = userMapper.selectList(null);
        userList.forEach(System.out::println);
    }

}

测试失败,原因在于id,name,user在Oracle数据库中为关键字,我们需要去实体类对其添加注解,添加完注解再次测试既能成功。

### SQL: SELECT  id,name,age,email  FROM user
### Cause: java.sql.SQLSyntaxErrorException: ORA-00903: 表名无效
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("\"user\"")
public class User {
    @TableId("\"id\"")
    private int id;
    @TableField("\"name\"")
    private String name;
    private Integer age;
    private String email;
}
User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)

配置日志

#    配置mybatis-plus日志,可以看到执行的查询语句
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
Preparing: SELECT "id","name",age,email FROM "user"

测试添加数据

    //测试添加数据
    @Test
    void insertDemo(){
        User user=new User();
        user.setId(110);
        user.setName("吴木木");
        user.setAge(21);
        user.setEmail("2289707466@qq.com");
        int insert = userMapper.insert(user);
        System.out.println(insert);
        System.out.println(user);
    }

这里的主键id是自己设置的,若想采用自增主键id或全球唯一id,可以使用 @TableId注解来实现,该注解提供了以下参数:

AUTO(0) 数据库id自增长
NONE(1) 未设置主键
INPUT(2) 手动输入
ASSIGN_ID(3) 全局唯一id
ASSIGN_UUID(4) 全局唯一id

但因为这里使用的是Oracle数据库,所以需要进行相应的配置,实现自增长主键参考另一篇博客:https://blog.csdn.net/weixin_49861429/article/details/108496686

测试更新操作

//测试更新数据
    @Test
    void updateDemo() {
        User user = new User();
        user.setId("1303872814919802882");
        user.setName("测试修改木木");
        userMapper.updateById(user);
    }

自动填充

在Oracle的数据库表中新增两个字段

create_time  date DEFAULT NULL,
  update_time date DEFAULT NULL,

使用注解填充字段

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

编写一个处理器类

@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
更新时,带上这个version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
乐观锁的配置只需三步
在Oracle数据库中新增version字段:

 "version" int DEFAULT 1

配置类配置

  //乐观锁
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

注解实体类字段

    @Version
    @TableField("\"version\"")
    private int version;

对乐观锁实现的成功与失败进行测试

//测试乐观锁成功案例
    @Test
    void hSuccessDemo() {
        User user = userMapper.selectById(1);
        user.setName("木木");
        user.setEmail("2289707466@qq.com");
        System.out.println(user);
        userMapper.updateById(user);
    }
 //测试乐观锁失败案例
    @Test
    void hFailureDemo() {
        User user1 = userMapper.selectById(2);
        user1.setName("木木一号");
        user1.setEmail("2289707466@qq.com");
        User user2 = userMapper.selectById(2);
        user2.setName("木木二号");
        user2.setEmail("2289707466@qq.com");
        userMapper.updateById(user2);
        userMapper.updateById(user1);
    }

从以下两行运行结果来看,可以看到在木木二号修改成功后version就加一了,那么木木一号在去对条件version为1时进行修改就会失败

==>  Preparing: UPDATE "user" SET "name"=?, age=?, email=?, update_time=?, "version"=? WHERE "id"=? AND "version"=?
==> Parameters: 木木二号(String), 20(Integer), 2289707466@qq.com(String), 2020-09-10 11:54:44.959(Timestamp), 2(Integer), 2(String), 1(Integer)
<==    Updates: 1
==>  Preparing: UPDATE "user" SET "name"=?, age=?, email=?, update_time=?, "version"=? WHERE "id"=? AND "version"=?
==> Parameters: 木木一号(String), 20(Integer), 2289707466@qq.com(String), 2020-09-10 11:54:44.968(Timestamp), 2(Integer), 2(String), 1(Integer)
<==    Updates: 0

查询测试

 //简单单条查询
    @Test
    void queryOneDemo(){
        User user=userMapper.selectById(1);
        System.out.println(user);
    }
    //多个id查询
    @Test
    void queryListDemo(){
        List<User> userList = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
        userList.forEach(System.out::println);
    }
    //条件查询
    @Test
    void queryByConditionDemo(){
        HashMap<String, Object> map = new HashMap<>();
        map.put("\"name\"","木木");
        map.put("age",18);
        List<User> userList = userMapper.selectByMap(map);
        userList.forEach(System.out::println);
    }

分页查询

分页插件

  //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }

测试

  //分页查询
    @Test
    void limitQueryDemo(){
        /**
         * 参数一:当前页码
         * 参数二:当前页面数据条数
         */
        Page<User> page = new Page<>(1,2);
        userMapper.selectPage(page,null);
        page.getRecords().forEach(System.out::println);
    }

删除操作

  //删除记录测试
    @Test
    void delGatherDemo(){
        //根据id删除
        userMapper.deleteById("ba9b69f506a0bfba663e0e51d6debab6");
        //根据id批量删除
        userMapper.deleteBatchIds(Arrays.asList("9addd99654f0340ffee1b8ad4db33b83","26c71d7e9ff567de262868c1251f9999"));
        //根据条件进行删除
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("\"name\"","吴木木");
        hashMap.put("age",21);
        userMapper.deleteByMap(hashMap);
    }

逻辑删除

往Oracle数据库表中增加字段

  deleted int default 0,

在yaml上配置

mybatis-plus:
  #日志,可以看到执行的查询语句
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  #逻辑删除配置
  global-config:
    db-config:
      logic-delete-field: deleted #逻辑删除的实体类字段名,配置该条实体字段不用加上注解
      logic-delete-value: 1 #逻辑删除的已删除值
      logic-not-delete-value: 0 #逻辑删除的已删除值

在实体类上添加字段

  @TableLogic //若在yaml配置文件中未配置,需添加该注解
    private int deleted;

性能分析插件

导入p6spy依赖

       <!-- https://mvnrepository.com/artifact/p6spy/p6spy -->
        <dependency>
            <groupId>p6spy</groupId>
            <artifactId>p6spy</artifactId>
            <version>3.9.1</version>
        </dependency>

yaml配置

spring:
#  oracle配置
  datasource:
    username: MYBATIS-PLUS
    password: Wzl7373520
    url: jdbc:p6spy:oracle:thin:@127.0.0.1:1521:ORCL
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver

spy.properties 配置:

#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat
# 自定义日志打印格式
customLogMessageFormat=%(currentTime) | SQL耗时: %(executionTime) ms | 连接信息: %(category)-%(connectionId) | 执行语句: %(sql)
#日志输出到控制台
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=1

测试结果:

2020-09-10 17:54:59 | SQL耗时: 35 ms | 连接信息: statement-0 | 执行语句: SELECT "id","name",age,email,create_time,update_time,"version",deleted FROM "user"  WHERE "name" = '木木' 
AND age = 18 
 AND deleted=0

代码生成器

依赖

 <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>3.0.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>3.0.0</version>
        </dependency>
        <!--添加代码生成器依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.2</version>
        </dependency>

生成器

/**
 * 代码生成器
 */
public class CodeGenerator {
    public static void main(String[] args) {
        //代码生成器
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        //获取用户的目录
        String projectPath = System.getProperty("user.dir");
        //输出目录
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("木木");//作者
        gc.setOpen(false);//是否打开资源管理器
        gc.setFileOverride(true);//是否覆盖原来生成的
        gc.setIdType(IdType.INPUT);//设置id生成策略
        gc.setDateType(DateType.ONLY_DATE);//设置日期的类型
        gc.setSwagger2(true); //实体属性 Swagger2 注解
        gc.setServiceName("%sService");//去掉默认的I前缀
        mpg.setGlobalConfig(gc);//将全局配置放入代码生成器中
        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:p6spy:oracle:thin:@127.0.0.1:1521:ORCL");
        dsc.setDriverName("com.p6spy.engine.spy.P6SpyDriver");
        dsc.setUsername("MYBATIS-PLUS");
        dsc.setPassword("Wzl7373520");
        dsc.setSchemaName("MYBATIS-PLUS");
        dsc.setDbType(DbType.ORACLE);//数据库类型
        dsc.setTypeConvert(new OracleTypeConvert(){
            @Override
            public IColumnType processTypeConvert(GlobalConfig config, String fieldType) {
                return super.processTypeConvert(config, fieldType);
            }
        });
        mpg.setDataSource(dsc);//将数据源配置放入代码生成器
        // 包配置
        PackageConfig pc = new PackageConfig();
        /**
         * 对目录名进行设置,若不设置,则采用默认
         */
        pc.setModuleName("generatedCode");
        pc.setParent("com.wuzneglin");
        pc.setEntity("pojo");
        pc.setController("controller");
        pc.setMapper("mapper");
        pc.setService("service");
//        pc.setServiceImpl("serviceImpl");
        mpg.setPackageInfo(pc);//将包配置放入代码生成器中
        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("wuzenglin");//数据库映射的表
        strategy.setNaming(NamingStrategy.underline_to_camel);//表名生成策略,下划线生成驼峰命名
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);//字段名生成策略,下划线生成驼峰命名
        strategy.setCapitalMode(false);			// 全局大写命名 ORACLE 注意
        //自定义实现父类
//        strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
        strategy.setEntityLombokModel(true);//自动使用lombok插件
        strategy.setRestControllerStyle(true);//生成@RestController控制器
        strategy.setControllerMappingHyphenStyle(true);//生成请求url
        //逻辑删除配置
        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");
        mpg.setStrategy(strategy);//将策略配置放入全局配置
        mpg.execute();//执行
    }
}
  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值