初识MyBatis-Plus框架

前言

之前刚看到MyBatis-Plus这个词的时候还以为又是一个新的框架,然而在了解之后却觉得一切都是为了偷懒而开发。以下内容是我在学习MyBatis-Plus时候做的笔记总结,学习视频为b站黑马程序员MyBatis-Plus p1-p62。如有错误请指正,谢谢。

MyBatis-Plus

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

快速开始

首先贴一下pom.xml文件如下:

<dependencies>
        <!-- mybatis-plus插件依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>3.1.1</version>
        </dependency>
        <!-- MySql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!-- 连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.11</version>
        </dependency>
        <!--简化bean代码的工具包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
            <version>1.18.4</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.4</version>
        </dependency>
    </dependencies>

还有数据库以及表:

-- 创建测试表 CREATE TABLE `tb_user` ( 
	`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', 
	`user_name` varchar(20) NOT NULL COMMENT '用户名', 
	`password` varchar(20) NOT NULL COMMENT '密码', 
	`name` varchar(30) DEFAULT NULL COMMENT '姓名',
	`age` int(11) DEFAULT NULL COMMENT '年龄', 
	`email` varchar(50) DEFAULT NULL COMMENT '邮箱', 
	PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 

-- 插入测试数据 INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('1', 'zhangsan', '123456', '张三', '18', '[email protected]'); 
INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('2', 'lisi', '123456', '李四', '20', '[email protected]'); 
INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('3', 'wangwu', '123456', '王五', '28', '[email protected]'); 
INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('4', 'zhaoliu', '123456', '赵六', '21', '[email protected]');
 INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('5', 'sunqi', '123456', '孙七', '24', '[email protected]');

Spring + MyBatis + MP

在这里插入图片描述
额外还需添加如下相关依赖:

<properties>
        <spring.version>5.1.6.RELEASE</spring.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>

log4.properties

log4j.rootLogger=DEBUG,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/lch?useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true&amp;allowMultiQueries=true&amp;useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>

applicationContext.xml
使用MP提供的sqlSessionFactory而不是MyBatis提供的。

<!-- 定义数据源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="maxActive" value="10"/>
        <property name="minIdle" value="5"/>
    </bean>

    <!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合-->
    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml" />
    </bean>

    <!--扫描mapper接口,使用的依然是Mybatis原生的扫描器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.hangzhou.mapper"/>
    </bean>

User.java
除了lombk的注解之外还添加了MP提供的@TableName(“tb_user”)(没错就是和数据库中的表名相同)

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {
    private Long id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;
}

UserMapper.interface
只需继承一个BaseMapper<pojo类型>

public interface UserMapper extends BaseMapper<User> {
}

Test.java
需要注意的是在test包下的环境也需要添加resources如下:
在这里插入图片描述

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestSpringMP {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelectList(){
        List<User> users = this.userMapper.selectList(null);
        for (User user:users
             ) {
            System.out.println(user);
        }
    }
}

控制台输出:
在这里插入图片描述

SpringBoot + MyBatis + MP

在这里插入图片描述
UserMapper和pojo.User与之前一样
application.properties

spring.application.name = mp-springboot
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/lch?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456

MyApplication.java

@MapperScan("com.hangzhou.mapper") //设置mapper接口的扫描包
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class,args);
    }
}

UserMapperTest.java

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelect(){
        List<User> users = userMapper.selectList(null);
        for (User user : users) {
            System.out.println(user);
        }
    }
}

核心功能

CRUD接口

之所以前面在自己的Mapper接口中去继承BaseMapper是因为在BaseMapper中已有多种CRUD的方法满足日常需求,而为什么只需要继承BaseMapper即可实现CRUD和如何自定义Sql语句也会在下面Sql注入器中说明。
在这里插入图片描述

插入操作

testInsert.java

@Test
public void testInsert(){
    User user = new User();
    user.setAge(18);
    user.setEmail("[email protected]");
    user.setName("ccc");
    user.setUserName("ccc");
    user.setPassword("123456");
    ////返回的result是受影响的行数,并不是自增后的id
    int result = userMapper.insert(user);
    System.out.println(result);
    System.out.println(user.getId());
}
@TableId

注意:如果没有在pojo类的id前面加上注解**@TableId**的类型,写入到数据库id的值是MP生成id的值(很大)而并非数据库的id进行自增,所以

@TableName("tb_user")
public class User {
    //指定id为自增长
    @TableId(type = IdType.AUTO)
    private Long id;
@TableField

在MP中通过@TableField注解可以指定字段的一些属性

  1. @TableField(value = “email”)对象中的属性名和字段名不一致的问题(非驼峰)
  2. @TableField(exist = false)可以解决对象中的属性字段在表中不存在的问题
  3. @TableField(select = false)对象中属性字段在查询时候不返回值

查询操作

selectById:根据 ID 查询。

@Test
public void testSelectById() {
    //根据id查询数据
    User user = this.userMapper.selectById(2L);
    System.out.println("result =" + user);
}

selectBatchIds:根据ID 批量查询。

@Test
public void testSelectBatchIds() {
    //根据id集合批量查询
    List<User> users = this.userMapper.selectBatchIds(Arrays.asList(2L, 3L, 10L));
    for (User user : users) {
    System.out.println(user);
}

selectOne:根据 entity 条件,查询一条记录。

@Test
public void testSelectOne() {
    QueryWrapper<User> wrapper = new QueryWrapper<User>();
    wrapper.eq("name","李四");
    //根据条件查询一条数据,如果结果超过一条会报错
    User user = this.userMapper.selectOne(wrapper);
    System.out.println(user);
}

更新操作

根据Id更新

testUpdateById.java

@Test
    public void testUpdateById() {
        User user = new User();
        user.setId(6L); //主键
       user.setAge(21); //更新的字段
       //根据id更新,更新不为null的字段
       this.userMapper.updateById(user);
    }
根据条件更新

@param entity 实体对象 (set 条件值,可以为 null);
@param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句);
int update(@Param(“et”) T entity, @Param(“ew”) Wrapper updateWrapper);
testUpdate.java(两种条件更新的方式)

@Test
public void testUpdate(){
    User user = new User();
    user.setAge(20);
    QueryWrapper<User> wrapper1 = new QueryWrapper<>();
    wrapper1.eq("id",1);
    int result1 = this.userMapper.update(user, wrapper1);
    System.out.println(result1);

    UpdateWrapper<User> wrapper2 = new UpdateWrapper<>();
    wrapper2.set("age",20).eq("id",20);
    int result2 = this.userMapper.update(null, wrapper2);
    System.out.println(result2);
}
删除操作

deleteById:根据 主键ID 删除。

@Test
public void testDeleteById() {
    //执行删除操作
    int result = this.userMapper.deleteById(6L);
    System.out.println("result =" + result);
}

deleteByMap:根据 columnMap 条件,删除记录。

@Test
public void testDeleteByMap() {
    Map<String, Object> columnMap = new HashMap<>();
    columnMap.put("age",20);
    columnMap.put("name","张三");
    //将columnMap中的元素设置为删除的条件,多个之间为and关系
    int result = this.userMapper.deleteByMap(columnMap);
    System.out.println("result =" + result);
}

delete:一种方式是wrapper作为删除条件;还有一种方式是将实体类对象包装成操作条件。

@Test
public void testDelete(){
    QueryWrapper<User> wrapper1 = new QueryWrapper<>();
    wrapper1.eq("name","ccc");
    int resulet1 = this.userMapper.delete(wrapper1);
    System.out.println(resulet1);

    User user = new User();
    user.setName("ccc");
    QueryWrapper<User> wrapper2 = new QueryWrapper<>(user);
    int result2 = this.userMapper.delete(wrapper2);
    System.out.println(result2);
}

配置

mapperLocations

MyBatis Mapper 所对应的 XML 文件位置,如果您在 Mapper 中有自定义方法(XML 中有自定义实现),需要进行该配置,告诉 Mapper 所对应的 XML 文件位置。
Mapper.java和Mapper.xml还是和MyBatis配置一样,但是在application配置中有所不同:
SpringBoot:在application.properties中配置

mybatis-plus.mapper-locations = classpath*:mybatis/*.xml

SpringMVC:在applicationContext.xml中配置

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
    <property name="mapperLocations" value="classpath*:mybatis/*.xml"/> 
</bean>

DB策略配置:idType

全局默认主键类型,设置后,即可省略实体对象中的@TableId(type = IdType.AUTO)配置。
SpringBoot:在application.properties中配置

mybatis-plus.global-config.db-config.id-type=auto

SpringMVC:在applicationContext.xml中配置

<!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合--> 
<bean id="sqlSessionFactory"class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> 
<property name="dataSource" ref="dataSource"/>
<property name="globalConfig">
<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
 <property name="dbConfig">
<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
                        <property name="idType" value="AUTO"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

DB策略配置:tablePrefix

表名前缀,全局配置后可省略pojo类中@TableName()配置。
SpringBoot:在application.properties中配置

mybatis-plus.global-config.db-config.table-prefix=tb_

SpringMVC:在applicationContext.xml中配置

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="globalConfig">
        <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig"> <property name="dbConfig">
        <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
                        <property name="idType" value="AUTO"/>
                        <property name="tablePrefix" value="tb_"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

条件构造器

QueryWrapper是用来当作条件构造器的一个类。

QueryWrapper<T> wrapper = new QueryWrapper<>();

基本比较操作

eq 等于 = 
ne 不等于 <> 
gt 大于 >  
ge 大于等于 >= 
lt 小于 < 
le 小于等于 <= 
between BETWEEN 值1 AND 值2 
notBetween NOT BETWEEN 值1 AND 值2 
in 字段 IN (value.get(0), value.get(1), ...)
notIn 字段 not in(v0,v1...)

模糊查询

like
LIKE '%值%': like("name", "王") ---> name like '%王%' 

notLike
NOT LIKE '%值%': notLike("name","王")---> name not like '%王%' 

likeLeft
LIKE '%值': likeLeft("name", "王") ---> name like '%王' 

likeRight
LIKE '值%': likeRight("name", "王") ---> name like '王%'

排序

orderBy
排序:ORDER BY 字段, ...: orderBy(true,true,"id","name")---> order by id,name ASC 

orderByAsc
排序:ORDER BY 字段, ... ASC
例: orderByAsc("id", "name") ---> order by id ASC,name ASC 

orderByDesc
排序:ORDER BY 字段, ... DESC
例: orderByDesc("id", "name") ---> order by id DESC,name DESC

逻辑查询

or
拼接 OR
主动调用 or 表示紧接着下一个方法不是用 and 连接!(不调用 or 则默认为使用 and 连接)

and
AND 嵌套
例: and(i -> i.eq("name", "李白").ne("status", "活着")) --> (name = '李白' and status <> '活着' )

Test.java

@Test
    public void testWrapper() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //SELECT id,user_name,password,name,age,email FROM tb_user WHERE name = ? OR age = ?
        wrapper.eq("name","李四").or().eq("age", 24);
        List<User> users = this.userMapper.selectList(wrapper); for (User user : users) {
        System.out.println(user); 
}

查询指定字段

在MP查询中,默认查询所有的字段,如果有需要也可以通过select方法进行指定字段。
Test.java

@Test
public void testWrapper() {
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //SELECT id,name,age FROM tb_user WHERE name = ? OR age = ?
    wrapper.eq("name", "李四") .or()
        .eq("age", 24)
        .select("id", "name", "age");
    List<User> users = this.userMapper.selectList(wrapper); for (User user : users) {
    System.out.println(user); 
}

ActiveRecord

ActiveRecord也属于ORM(对象关系映射)层,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。
ActiveRecord的主要思想是:

  1. 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录通常表的每个字段在类中都有相应的Field。
  2. ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD。
  3. ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑。

快速开始

只需要将实体对象继承Model然后使用实体对象其中的方法即可实现CRUD。
pojo.java

@Data
@NoArgsConstructor
@AllArgsConstructor
//@TableName("tb_user")
public class User extends Model<User> {

在这里插入图片描述
Test.java

@Test
public void testSelectById(){
    User user = new User();
    user.setId(2L);

    User user1 = user.selectById(user);
    System.out.println(user1);
}

Sequence主键

在mysql中,主键往往是自增长的,这样使用起来是比较方便的,如果使用的是Oracle数据库,那么就不能使用自增
长了,就得使用Sequence 序列生成id值了。

Oracle

创建序列

--创建序列
CREATE SEQUENCE SEQ_USER START WITH 1 INCREMENT BY 1

修改application.properties

#数据库连接配置 
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver 
spring.datasource.url=
spring.datasource.username=system 
spring.datasource.password=oracle
#id生成策略 (关闭之前主键Auto自增)
mybatis-plus.global-config.db-config.id-type=input

配置序列:第一步需要配置MP的序列生成器到Spring容器;然后在实体对象中指定序列的名称。

@Configuration
@MapperScan("cn.itcast.mp.mapper") //设置mapper接口的扫描包 
public class MybatisPlusConfig {
/**
* 分页插件 
*/
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
/**
* 序列生成器 
*/
    @Bean
    public OracleKeyGenerator oracleKeyGenerator(){
        return new OracleKeyGenerator();
    } 
}

pojo.java

@KeySequence(value = "SEQ_USER", clazz = Long.class) 
public class User{
......
}

插件扩展

MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) 
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)

总体概括为:

  1. 拦截执行器的方法
  2. 拦截参数的处理
  3. 拦截结果集的处理
  4. 拦截Sql语法构建的处理

拦截器

MyInterceptor.java

@Intercepts({@Signature( type= Executor.class,
        method = "update",
args = {MappedStatement.class,Object.class})}) 
public class MyInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable { 
        //拦截方法,具体业务逻辑编写的位置
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object target) { 
        //创建target对象的代理对象,目的是将当前拦截器加入到该对象中 return Plugin.wrap(target, this);
        return Plugin.wrap(target, this);
    }
    @Override
    public void setProperties(Properties properties) { //属性设置
    } 
}

执行分析插件

在MP中提供了对SQL执行的分析的插件,可用作阻断全表更新、删除的操作,注意:该插件仅适用于开发环境,不
适用于生产环境。
MybatisPlusConfig.java

@Bean
public SqlExplainInterceptor sqlExplainInterceptor(){
    SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
    List<ISqlParser> sqlParserList = new ArrayList<>();
    //全表更新、删除的阻断器
    sqlParserList.add(new BlockAttackSqlParser());
    sqlExplainInterceptor.setSqlParserList(sqlParserList);

    return sqlExplainInterceptor;
}

Test.java

@Test
public void testUpDateAll(){
    User user = new User();
    user.setAge(28);
    //没有限制条件进行全表更新
    boolean result = user.update(null);
    System.out.println("result : "+result);
}

控制台输出:
在这里插入图片描述

性能分析插件

性能分析拦截器,用于输出每条 SQL 语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常。注意:该插件仅适用于开发环境,不适用于生产环境。
基于xml的配置:

<configuration>
    <plugins>
        <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor">
            <!-- sql执行最长时间 -->
            <property name="maxTime" value="100"/>
            <!-- sql语句格式化 -->
            <property name="format" value="true"/>
        </plugin>
    </plugins>
</configuration>

Test.java

@Test
public void testSelectById(){
    User user = new User();
    user.setId(2L);

    User user1 = user.selectById(user);
    System.out.println(user1);
}

控制台输出:在这里插入图片描述

乐观锁插件

当要更新一条记录的时候,希望这条记录没有被别人更新过。
实现方式:取出记录时,获取当前version;更新时,带上这个version;执行更新时, set version = newVersion where version = oldVersion 如果version不对,就更新失败。

实现乐观锁

spring xml配置:

<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>

SpringBoot配置:

@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    return new OptimisticLockerInterceptor();
}

mybatis-config.xml

<plugins>
    <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"></plugin>
</plugins>

在数据库中为表添加version字段并且设置初始值为1

ALTER TABLE `tb_user`
ADD COLUMN `version` int(10) NULL AFTER `email`;

UPDATE `tb_user` SET `version`='1';

为User实体对象添加version字段并且添加@Version注解

@Version
private Integer version;

乐观锁特别说明

支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime 
整数类型下 newVersion = oldVersion + 1
newVersion 会回写到 entity 中
仅支持 updateById(id)update(entity, wrapper) 方法 
在 update(entity, wrapper) 方法下, wrapper 不能复用!!!

Sql注入器

在MP中接口ISqlInjector负责SQL的注入工作,AbstractSqlInjector是它的实现类。而在AbstractSqlInjector中主要是由inspectInject()方法实现,最终实现AbstractMethod中的方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实现自定义Mapper

在MP中,通过AbstractSqlInjector将BaseMapper中的方法注入到了Mybatis容器,这样这些方法才可以正常执行,但是有时候还是需要扩充BaseMapper中的方法。
在这里插入图片描述
编写MyBaseMapper:

public interface MyBaseMapper<T> extends BaseMapper<T> {
    List<T> findAll();
}

其他的Mapper都可以继承该Mapper,这样实现了统一的扩展。如:

public interface UserMapper extends MyBaseMapper<User> {

编写MySqlInjector的时候如果直接继承AbstractSqlInjector的话,原有的BaseMapper中的方法将失效,因为要override所有的方法,所以我们选择继承DefaultSqlInjector 进行扩展。

public class MySqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList() {
        List<AbstractMethod> methodList = super.getMethodList();
        methodList.add(new FindAll());
        return methodList;
    }
}

编写FindAll,继承AbstractMethod抽象类,可以查看AbstractMethod类的子类的编写方法。但是教学视频中没有详细说明方法中参数的作用。

public class FindAll extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sqlMethod = "findAll";
        String sql = "select * from " + tableInfo.getTableName();
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addSelectMappedStatement(mapperClass,sqlMethod,sqlSource,modelClass,tableInfo);
    }
}

注册到容器中即可使用自定义Mapper:

@Bean
public MySqlInjector mySqlInjector(){
    return new MySqlInjector();
}

自动填充功能

有些时候我们可能会有这样的需求,插入或者更新数据时,希望有些字段可以自动填充数据,比如密码、version 等。在MP中提供了这样的功能,可以实现自动填充。
添加@TableField注解

@TableField(fill = FieldFill.INSERT)
private String password;

编写MyMetaObjectHandler:

package com.hangzhou.handle;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        Object password = getFieldValByName("password", metaObject);
        if(null == password){
            setFieldValByName("password","123456",metaObject);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {

    }
}

逻辑删除

开发系统时,有时候在实现功能时,删除操作需要实现逻辑删除,所谓逻辑删除就是将数据标记为删除,而并非真正的物理删除(非DELETE操作),查询时需要携带状态条件,确保被标记的数据不被查询到。这样做的目的就是避免数据被真正的删除。
修改表结构,为tb_user表增加deleted字段,用于表示数据是否被删除,1代表删除,0代表未删除。
也修改User实体类,增加deleted属性并且添加@TableLogic注解:

@TableLogic
private Integer deleted;

配置application.properties:

# 逻辑已删除值(默认为 1) 
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑未删除值(默认为 0) 
mybatis-plus.global-config.db-config.logic-not-delete-value=0

Test.java

@Test
public void testDeleteById(){
    int result = this.userMapper.deleteById(8L);
    System.out.println(result);
}

控制台输出:(可以看到where条件后加了一个 deleted = 0)
在这里插入图片描述
然后再去搜索这个对象的时候却搜索不到是也是因为where条件后加了一个 deleted = 0,而此时的 deleted = 1。

通用枚举

修改表结构

ALTER TABLE `tb_user`
ADD COLUMN `sex` int(1) NULL DEFAULT 1 COMMENT '1-男,2-女' AFTER `deleted`;

定义枚举SexEnum.java

public enum SexEnum implements IEnum<Integer> {

    MAN(1,"男"),
    WOMAN(2,"女");

    private int value;
    private String desc;
    SexEnum(int value, String desc) { this.value = value;
        this.desc = desc;
    }

    @Override
    public Integer getValue() {
        return this.value;
    }

    @Override
    public String toString() {
        return this.desc;
    }
}

修改配置以及修改实体类

# 枚举包扫描
mybatis-plus.type-enums-package=com.hangzhou.enums
private SexEnum sex;

Test.java

@Test
public void testInsertEnum(){
    User user = new User();
    user.setName("c");
    user.setUserName("c");
    user.setAge(18);
    user.setMail("[email protected]");
    user.setVersion(1);
    user.setSex(SexEnum.WOMAN);

    int result = this.userMapper.insert(user);
    System.out.println(result);
}

控制台Sql输出:
在这里插入图片描述
再去select该对象的时候控制台输出可观察到输出自动把来自数据库的int类数转换成对于的varchar。
在这里插入图片描述

代码生成器

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper
XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
详情见代码生成器

MyBatisX 快速开发

MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
详情见快速开发

结束语

其实对于MP在有一个入门之后更多的学习还要参考MP官方文档进行,也正是因为对于MP有了一个初步了解所以才发现当前所在实习公司的大数据在线服务平台中有照着MP的思想开发出来的一个东西,截取部分贴在下面仅供瞻仰。学的越多不懂的越多,长路漫漫。
在这里插入图片描述
在这里插入图片描述
在这个SqlSession接口中和MP的想法一致,也许是因为MP的功能满足不了公司的sql业务需求并且自定义Mapper又需要学习成本。如有错误请指正!
在这里插入图片描述

发布了4 篇原创文章 · 获赞 2 · 访问量 1412

猜你喜欢

转载自blog.csdn.net/weixin_45468390/article/details/104358041