MyBatis-Plus---增强型mybatis

MyBatis-Plus---增强型mybatis_第1张图片

指定数据库表名

@TableName("tianshu_log_event")
//@IdClass(EventCompositePK.class) // 联合主键
public class Event implements Serializable {

    private static final long serialVersionUID = 1L;
    public static final String TABLE_NAME = "tianshu_log_event";

 指定主键字段

@TableId(value = "id", type = IdType.ASSIGN_ID) //生成id的类型:数据库自增(AUTO)、默认id生成器(ASSIGN_ID)、自定义id生成器(INPUT)
    private Long id;

 映射属性和表字段

@TableField(value = "content")
    private String content;

 不参与序列化,不会作为数据字段

private transient Integer eventId;
private static Integer eventId;
 @TableField(exist = false)
    private Integer eventId;

 

CRUD

 

条件构造器

com.baomidou.mybatisplus.core.conditions.AbstractWrapper

第3章 MyBatis-Plus查询方法

本章主要介绍MyBatis-Plus查询的主要内容,包括普通查询、条件构造器查询、select不列出全部字段查询等内容。

  •  3-1 普通查询 (10:31)
  •  3-3 条件构造器查询(2) (07:28)
QueryWrapper
new QueryWrapper().orderBy(true, !isDesc, orderBy)
    .like(Boolean.valueOf(nameLike), searchName, searchValue);
  •  3-4 条件构造器查询(3) (05:21)

MyBatis-Plus---增强型mybatis_第2张图片

  •  3-5 条件构造器查询(4) (05:54)
  •  3-6 select不列出全部字段 (05:29)

只列出id和owner字段

wrapper.select("id", "owner").likeLeft("owner", "sp").gt("level", 3);

不列出owner和content字段(对主键:id不生效)

wrapper.likeLeft("owner", "sp").gt("level", 3)
                .select(
                        Event.class
                        , info -> !info.getColumn().equals("owner") && !info.getColumn().equals("content"));
  •  3-7 condition作用 (06:47)
  •  3-8 实体作为条件构造器构造方法的参数 (06:24)
  •  3-9 AllEq用法 (06:10)
  •  3-10 其他使用条件构造器的方法 (10:36)
  •  3-11 lambda条件构造器 (09:49)

第4章 自定义sql及分页查询

本章介绍MyBatis-Plus中自定义sql和分页查询的内容。

  •  4-1 自定义sql (07:16)
  •  4-2 分页查询 (13:41)

第5章 更新及删除

介绍MyBatis-Plus中更新和删除功能的使用。

  •  5-1 更新方法 (15:10)
  •  5-2 删除方法 (09:58)

第6章 AR模式、主键策略和基本配置

本章介绍MyBatis-Plus中的AR模式、主键策略和基本配置等内容。

  •  6-1 AR模式 (12:09)
@Mapper
public interface EventMapper extends BaseMapper {
    ...
}
public class Event extends Model implements Serializable {

    private static final long serialVersionUID = 1L;

    ...
}
@Autowired
private Event event;

@GetMapping(path = "/ActiveRecord/{id}/")
    public ResponseEntity activeRecord(@PathVariable Long id){
        Event event = this.event.selectById(id);
        return this.responseEntity.success(event);
    }

 

PS:

mapper的装配方式:

1、接口注解装配

@Mapper
public interface EventMapper extends BaseMapper {
    ...
}

2、统一装配

@EnableTransactionManagement
@Configuration
@MapperScan(value = {"ik.starriver.log.mapper*"})
public class MyBatisPlusAutoConfiguration {
....
}
  •  6-2 主键策略 (11:49)

局部策略设置在表实体上 

public class Event extends Model implements Serializable {

    @TableId(value = "id", type = IdType.ASSIGN_UUID) //生成id的类型:数据库自增(AUTO)、默认id生成器(ASSIGN_ID)、自定义id生成器(INPUT)
    private Long id;

全局策略设置在配置文件中

mybatis-plus:
  global-config:
    db-config:
      id-type: ASSIGN_ID

 

  •  6-3 基本配置 (14:34)

多模块模式下:要在classpath后面加 “ * ”

mybatis-plus:
  type-handlers-package: ik.starriver.log.handler*
  mapper-locations: classpath*:/mapper*/*Mapper.xml #

 字段生成策略(局部也可以设置,局部优于全局)

global-config:
    db-config:
    #未设置字段sql语句生成的策略 IGNORED:"直接设置为null",NOT_NULL:"可以插入设置的空字符串"),NOT_EMPTY:"未设置和空字符串都不会插入"
      field-strategy: not_empty

 局部配置

@TableField(whereStrategy = FieldStrategy.IGNORED)
private String description;
2020-02-28 02:14:29.835 [DEBUG] [http-nio-9000-exec-1] ik.starriver.log.mapper.EventMapper.selectList:143 : ==>  Preparing: SELECT id,content,create_time,description,level,owner FROM tianshu_log_event WHERE description=? AND level=?  
2020-02-28 02:14:29.851 [DEBUG] [http-nio-9000-exec-1] ik.starriver.log.mapper.EventMapper.selectList:143 : ==> Parameters: null, 3(Integer) 
2020-02-28 02:14:29.937 [DEBUG] [http-nio-9000-exec-1] ik.starriver.log.mapper.EventMapper.selectList:143 : <==      Total: 0 

 

PS:

字段生成策略也会影响参数为实体的wrapper

MyBatis-Plus---增强型mybatis_第3张图片

字段策略为ignored

MyBatis-Plus---增强型mybatis_第4张图片

sql语句中未设置字段全部插入null

 

 

第7章 通用service

本章介绍通用service的内容。

  •  7-1 通用service (14:58)

 

mybatis进阶

 

第1章 概述

本章介绍课程的主要内容,课程涉及的表结构,以及项目的基本情况。

  •  1-1 高级功能课程简介 (02:13)

 

  •  1-2 基础数据表和基础项目介绍 (05:58)

第2章 逻辑删除

本章主要介绍MyBatis-Plus中逻辑删除的内容。

  •  2-1 逻辑删除简介 (01:45)

逻辑删除:假删除(通过标识字段是否删除,来表示数据删除与否,不会真实删除数据)

配置文件全局设置

{
      "name": "mybatis-plus.global-config.db-config.logic-delete-value",
      "type": "java.lang.String",
      "sourceType": "com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig"
    },
    {
      "name": "mybatis-plus.global-config.db-config.logic-not-delete-value",
      "type": "java.lang.String",
      "sourceType": "com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig"
    },

 注解逻辑删除字段

MyBatis-Plus---增强型mybatis_第5张图片

  •  2-2 逻辑删除实现 (10:41)

 

执行删除,实际是update操作,将deleted设置为1,表示逻辑已删除

MyBatis-Plus---增强型mybatis_第6张图片

MyBatis-Plus---增强型mybatis_第7张图片

MyBatis-Plus---增强型mybatis_第8张图片

全部查询,只会返回deleted=0的数据

 

MyBatis-Plus---增强型mybatis_第9张图片

更新同理

MyBatis-Plus---增强型mybatis_第10张图片

  •  2-3 查询中排除删除标识字段及注意事项 (05:40)
@TableField(select = false)
private Integer deleted;

 select排除deleted字段,不查询

PS:

对自定义sql不生效

public interface EventMapper extends BaseMapper {

    @Select("select id, content from tianshu_log_event where id = #{id}")
    Event selectByIdSQL(Long id);

须自行过滤deleted字段 

第3章 自动填充

本章主要介绍MyBatis-Plus自动填充及优化的内容。

  •  3-1 自动填充简介 (01:31)
  •  3-2 自动填充实现 (08:08)

申明需要自动填充的字段

@TableField(fill = FieldFill.INSERT_UPDATE)
    private Timestamp createTime;

实现MetaObjectHandler 接口,书写填充逻辑(注意:fieldname是java属性名不是数据库字段名)

package ik.starriver.log.autoconfigure;

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

import java.sql.Timestamp;
import java.text.SimpleDateFormat;

@Component
public class DefaultMetaObjectHandler implements MetaObjectHandler {

    private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    @Override
    public void insertFill(MetaObject metaObject) {

        boolean createTime = metaObject.hasSetter("createTime");
        Object objVal = getFieldValByName("createTime", metaObject);
        if (createTime && null == objVal){
            this.strictInsertFill(metaObject,"createTime", Timestamp.class, Timestamp.valueOf(formatter.format(System.currentTimeMillis())));
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        boolean createTime = metaObject.hasSetter("createTime");
        Object objVal = getFieldValByName("createTime", metaObject);
        if (createTime && null == objVal){
            this.strictUpdateFill(metaObject,"createTime", Timestamp.class, Timestamp.valueOf(formatter.format(System.currentTimeMillis())));
        }
    }
}

 中文乱码:characterEncoding=utf8

时间错误:serverTimezone=GMT%2B8

数据库连接SSL报错:useSSL=false

public class ApplicationAutoConfiguration {
    private final static String DATABASE_URL = "jdbc:mysql://10.1.252.23:3306/springtest?serverTimezone=GMT&useSSL=false&characterEncoding=utf8";

 

  •  3-3 自动填充优化 (06:22)

插入时只有带有createTime1字段的语句才会自动生成时间(节省了自动生成时间所需开销)

MyBatis-Plus---增强型mybatis_第11张图片

更新时只有指定字段没有设置值,才会自动填充

 MyBatis-Plus---增强型mybatis_第12张图片

第4章 乐观锁

本章介绍MyBatis-Plus乐观锁的实现。

  •  4-1 乐观锁简介 (02:22)

多读小写乐观锁

多写少读悲观锁

 

  •  4-2 乐观锁实现及注意事项 (09:08)

wrapper不能复用!!!!

 

第5章 性能分析

本章主要介绍MyBatis-Plus的性能分析、参数设置和执行sql分析打印等内容。

  •  5-1 性能分析实现及参数设置 (05:18)
@Bean
    @Profile({"dev","test"})
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor interceptor = new PaginationInterceptor();
        interceptor.setLimit(100);
        interceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return interceptor;
    }

  •  5-2 执行sql分析打印 (06:44)

PS:

https://mybatis.plus/guide/performance-analysis-plugin.html

第6章 多租户

本章介绍MyBatis-Plus多租户的概念及实现。

  •  6-1 多租户概念介绍 (02:51)

多租户方式:

分库,每个用户一个数据库,数据安全,便于恢复

统一库,分schema

统一库,统一schema,分表

 

  •  6-2 多租户实现 (09:11)
@Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        /*
         * 【测试多租户】 SQL 解析处理拦截器
* 这里固定写成住户 1 实际情况你可以从cookie读取,因此数据看不到 【 麻花藤 】 这条记录( 注意观察 SQL )
*/ List sqlParserList = new ArrayList<>(); TenantSqlParser tenantSqlParser = new MyTenantParser(); tenantSqlParser.setTenantHandler(new TenantHandler() { /** * 2019-8-1 * * https://gitee.com/baomidou/mybatis-plus/issues/IZZ3M * * tenant_id in (1,2) * @param where 如果是where,可以追加,不是where的情况:比如当insert时,不能insert into user(name, tenant_id) values('test', tenant_id IN (1, 2)); * @return */ @Override public Expression getTenantId(boolean where) { final boolean multipleTenantIds = true;//这里只是演示切换单个tenantId和多个tenantId //具体场景,可以根据情况来拼接 if (where && multipleTenantIds) { //演示如何实现tenant_id in (1,2) return multipleTenantIdCondition(); } else { //演示:tenant_id=1 return singleTenantIdCondition(); } } private Expression singleTenantIdCondition() { return new LongValue(1);//ID自己想办法获取到 } private Expression multipleTenantIdCondition() { final InExpression inExpression = new InExpression(); inExpression.setLeftExpression(new Column(getTenantIdColumn())); final ExpressionList itemsList = new ExpressionList(); final List inValues = new ArrayList<>(2); inValues.add(new LongValue(1));//ID自己想办法获取到 inValues.add(new LongValue(2)); itemsList.setExpressions(inValues); inExpression.setRightItemsList(itemsList); return inExpression; } @Override public String getTenantIdColumn() { return "tenant_id"; } @Override public boolean doTableFilter(String tableName) { // 这里可以判断是否过滤表 /*if ("user".equals(tableName)) { return true; }*/ // return false; return !"user".equalsIgnoreCase(tableName); } }); sqlParserList.add(tenantSqlParser); paginationInterceptor.setSqlParserList(sqlParserList); // paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() { // @Override // public boolean doFilter(MetaObject metaObject) { // MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject); // // 过滤自定义查询此时无租户信息约束【 麻花藤 】出现 // if ("com.baomidou.springboot.mapper.UserMapper.selectListBySQL".equals(ms.getId())) { // return true; // } // return false; // } // }); return paginationInterceptor; }
  •  6-3 特定sql过滤 (08:00)

第7章 动态表

本章主要介绍MyBatis-Plus动态表的实现及注意事项。

  •  7-1 动态表名的应用场景 (01:57)

相同表结构,分表存储,如日志按月分表,按企业对象分表等

  •  7-2 动态表名实现 (08:13)
  •  7-3 注意事项 (04:24)

第8章 SQL注入器

本章主要介绍SQL注入器,和选装件的内容。

  •  8-1 SQL注入器简介及自定义方法实现 (13:29)

自定义Method

package ik.starriver.log.sqlinjector.methods;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

public class DeleteAllMethod extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) {

        String mapperName = "deleteAll";
        String sql = "DELETE FROM " + tableInfo.getTableName();
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);

        return addDeleteMappedStatement(mapperClass,mapperName,sqlSource);
    }
}

添加到list中,注解装配到Spring IoC容器中

package ik.starriver.log.sqlinjector;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import ik.starriver.log.sqlinjector.methods.DeleteAllMethod;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class CustomizedSqInjector extends DefaultSqlInjector {

    @Override
    public List getMethodList(Class mapperClass) {
        List methodList = super.getMethodList(mapperClass);
        methodList.add(new DeleteAllMethod());
        return methodList;
    }
}

 AutoConfiguration @Bean的方式装配

    @Bean
    public DefaultSqlInjector defaultSqlInjector(){
        CustomizedSqInjector defaultSqlInjector = new CustomizedSqInjector();
        return defaultSqlInjector;
    }
  •  8-2 选装件InsertBatchSomeColumn (07:38)
  •  8-3 选装件LogicDeleteByIdWithFill (04:13)
  •  8-4 选装件alwaysUpdateSomeColumnById (03:53)

字段类型处理器

@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User {
    private Long id;

    ...


    /**
     * 注意!! 必须开启映射注解
     *
     * @TableName(autoResultMap = true)
     *
     * 以下两种类型处理器,二选一 也可以同时存在
     *
     * 注意!!选择对应的 JSON 处理器也必须存在对应 JSON 解析依赖包
     */
    @TableField(typeHandler = JacksonTypeHandler.class)
    // @TableField(typeHandler = FastjsonTypeHandler.class)
    private OtherInfo otherInfo;

}
@TableName(value = "tianshu_log_event"
            , autoResultMap = true
)
public class Event extends BaseModel {
    /**
     * 注意!! 必须开启映射注解
     *
     * @TableName(autoResultMap = true)
     *
     * 以下两种类型处理器,二选一 也可以同时存在
     *
     * 注意!!选择对应的 JSON 处理器也必须存在对应 JSON 解析依赖包
     */
    @JsonDeserialize(using = EventLevelDeserializer.class)
    @TableField(typeHandler = EventLevelHandler.class) //开启autoResultMap后才能使用调到指定的handler
    @JsonSerialize(using = EventLevelSerializer.class)
    private EventLevelEnum level;

 

你可能感兴趣的:(mybatis)