Mybatis plus集成

参考:
MyBatis-Plus - 官网

一、maven依赖

  <!-- mybatis-plus -->
  <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.4.2</version>
  </dependency>

完整springboot maven依赖

<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/>
    </parent>
    <groupId>com.mx</groupId>
    <artifactId>mybatis-plus-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>mybatis-plus-demo</name>
    <properties>
        <java.version>1.8</java.version>
        <mybatis.plus.version>3.4.2</mybatis.plus.version>
    </properties>

    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <scope>compile</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>compile</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis.plus.version}</version>
        </dependency>

        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

二、通过Mybatis-Plus生成器生成代码

1、生成代码

生成代码可参考我的另一篇博文:Mybatis plus代码生成器
然后将生成后的代码以及mapper.xml拷贝到对应的工程内:
在这里插入图片描述

2、配置mybatis - @MapperScan、分页插件
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Mybatis-Plus配置
 *
 * @author luohq
 * @date 2021-02-01
 */
@Configuration
@MapperScan("com.mx.demo.mapper")
public class MybatisPlusConfig {

    /**
     * 新的分页插件,
     * 一缓和二缓遵循mybatis的规则,
     * 需要设置 MybatisConfiguration#useDeprecatedExecutor = false
     * 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return configuration -> configuration.setUseDeprecatedExecutor(false);
    }
}
3、spring application配置
server:
    port: 8080
# =========================================================================
# ============================ mysql数据源连接配置 ==========================
# =========================================================================
spring:
    datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db_msg_push?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&nullCatalogMeansCurrent=true
        username: root
        password: root
        type: com.zaxxer.hikari.HikariDataSource
        hikari:
            # 连接池最少空闲连接数(默认10)
            minimum-idle: 10
            # 连接池中允许的最大连接数(默认10),推荐的公式:(core_count * 2) + effective_spindle_count
            maximum-pool-size: 20
            # 一个连接idle状态的最大时长(毫秒,>=10s,默认10分钟),超时则被释放(retired)
            idle-timeout: 600000
            # 等待连接池分配连接的最大时长(毫秒,>=250ms,默认30秒),超过这个时长还没可用的连接则发生SQLException
            connection-timeout: 30000
            # JDBC4支持conn.isValid(int timeout),可禁用该属性
            # connection-test-query: SELECT 1
            # 验证连接aliveness(即每次从连接池获取connection前调用conn.isValid(timeout)的超时时间)的超时时长
            # (毫秒,>=250ms,默认5s,需要小于connection-timeout,若小于250ms则重置为5s)
            validation-timeout: 5000
            # 连接只读数据库时配置为true, 保证安全
            read-only: false
            # 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired)(>=30s,默认30分钟)
            # 建议设置比数据库超时时长少30秒,参考MySQL wait_timeout(默认28800s,即8小时)参数(show variables like '%timeout%';)
            max-lifetime: 1800000
            # 设置是否自动提交事务
            auto-commit: true
            # 连接池名称
            pool-name: LuoHikariCP
# =========================================================================
# ============================ mybatis配置 ================================
# =========================================================================
mybatis:
    mapperLocations: classpath:mapper/*.xml
    typeAliasesPackage: com.mx.demo.model.entity

三、使用Mybatis-Plus

查看生成代码发现Mapper继承了BaseMapper,Service都继承了IService,这两个基类都内置了一些常规的CRUD操作,对于单表的操作基本不需要再自定义mapper.xml了,而对于一些复杂的连接查询,还是可以通过自定义mapper.xml来进行的。
在这里插入图片描述
并且在新版本的Mybatis-Plus中支持Java8 Lamba表达式,即可以通过Lamba表达式进行column名称的设置,避免了最开始的字面量(字符串)设置;
在这里插入图片描述

以下为几个简单示例:

package com.mx.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mx.demo.enums.RespCodeEnum;
import com.mx.demo.mapper.MsgPushMapper;
import com.mx.demo.model.entity.MsgPush;
import com.mx.demo.model.entity.MsgTarget;
import com.mx.demo.model.param.FindMsgPushParam;
import com.mx.demo.model.param.MsgPushParam;
import com.mx.demo.model.param.PageBaseParam;
import com.mx.demo.model.result.RespResult;
import com.mx.demo.service.IMsgPushService;
import com.mx.demo.service.IMsgTargetService;
import com.mx.demo.utils.CommonUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 消息推送 服务实现类
 * </p>
 *
 * @author luohq
 * @since 2021-01-31
 */
@Service
public class MsgPushServiceImpl extends ServiceImpl<MsgPushMapper, MsgPush> implements IMsgPushService {


    @Resource
    private IMsgTargetService msgTargetService;

    @Override
    public RespResult addMsgPush(MsgPushParam msgPushParam) {

        /** 保存msgPush */
        MsgPush msgPush = this.convertMsgPush(msgPushParam);
        //执行保存操作
        Boolean success = this.save(msgPush);

        /** 保存消息目标 */
        List<MsgTarget> msgTargetList = this.convertMsgTargetList(msgPush, msgPushParam);
        //执行批量保存操作
        success = this.msgTargetService.saveBatch(msgTargetList);

        return RespResult.buildWith(success);
    }

    @Override
    public RespResult<MsgPush> findMsgPushList(FindMsgPushParam param) {
        //(create_time >= #{startCreateTime} and create_time <= #{endCreateTime})
        //and (id = #{id} or msg_content like concat('%', #{msgContent}, '%'))
        LambdaQueryWrapper queryWrapper = Wrappers.<MsgPush>lambdaQuery()
                .ge(ObjectUtils.isNotNull(param.getStartCreateTime()), MsgPush::getCreateTime, param.getStartCreateTime())
                .le(ObjectUtils.isNotNull(param.getEndCreateTime()), MsgPush::getCreateTime, param.getEndCreateTime())
                .and(lqw -> lqw.eq(ObjectUtils.isNotNull(param.getId()), MsgPush::getId, param.getId())
                        .or().like(ObjectUtils.isNotEmpty(param.getMsgContent()), MsgPush::getMsgContent, param.getMsgContent()));

        /* 以下为原QueryWrapper,需要使用字面量,且字面量需通过大量常量进行维护
        QueryWrapper queryWrapper = Wrappers.query().eq("id", 1L).like("msg_content", "hello");
        QueryWrapper queryWrapper = Wrappers.query()
                .eq("id", 1L).or().like("msg_content", "hello")
                .and(wrapper -> wrapper.ge("update_time", param.getStartUpdateTime()).le("update_time", param.getEndUpdateTime()))
                .and(wrapper -> wrapper.ge("create_time", param.getStartCreateTime()).le("create_time", param.getEndCreateTime()));
        */
        List<MsgPush> msgPushList = this.list(queryWrapper);
        return RespResult.buildSuccessRows(msgPushList);
    }

    @Override
    public RespResult<MsgPush> findMsgPushPage(FindMsgPushParam param) {
        //设置分页及排序参数
        Page page = this.convertPage(param);
        //构建查询条件
        Wrapper queryWrapper = this.buildListQueryMapper(param);
        //执行分页查询
        IPage<MsgPush> pageResult = this.page(page, queryWrapper);
        //转换分页查询结果
        return RespResult.buildSuccessRows(pageResult.getRecords(), pageResult.getTotal());
    }

    /**
     * 转换mp分页参数
     *
     * @param pageBaseParam
     * @return
     */
    private Page convertPage(PageBaseParam pageBaseParam) {
        Page page = new Page<>();
        page.setCurrent(pageBaseParam.getPage());
        page.setSize(pageBaseParam.getRows());
        page.addOrder(CommonUtils.convertSortOrderItem(pageBaseParam));
        return page;
    }

    /**
     * 构建查询条件
     *
     * @param param
     * @return
     */
    private Wrapper buildListQueryMapper(FindMsgPushParam param) {
        //id = #{id} and msg_content like concat('%', #{msgContent}, '%'))
        //and create_time >= #{startCreateTime} and create_time <= #{endCreateTime}
        return Wrappers.<MsgPush>lambdaQuery()
                .eq(ObjectUtils.isNotNull(param.getId()), MsgPush::getId, param.getId())
                .like(ObjectUtils.isNotEmpty(param.getMsgContent()), MsgPush::getMsgContent, param.getMsgContent())
                .ge(ObjectUtils.isNotNull(param.getStartCreateTime()), MsgPush::getCreateTime, param.getStartCreateTime())
                .le(ObjectUtils.isNotNull(param.getEndCreateTime()), MsgPush::getCreateTime, param.getEndCreateTime());
    }

    @Override
    public RespResult updateMsgPush(MsgPush msgPush) {
        //Boolean success = this.updateById(msgPush);
        Boolean success = this.update(Wrappers.<MsgPush>lambdaUpdate()
                //通过UpdateWrapper.set操作设置对应的set语句
                .set(StringUtils.isNotBlank(msgPush.getMsgContent()), MsgPush::getMsgContent, msgPush.getMsgContent())
                .set(ObjectUtils.isNotNull(msgPush.getPushType()), MsgPush::getPushType, msgPush.getPushType())
                .set(ObjectUtils.isNotNull(msgPush.getPushResult()), MsgPush::getPushResult, msgPush.getPushResult())
                .set(MsgPush::getUpdateTime, LocalDateTime.now())
                //设置update where条件
                .eq(MsgPush::getId, msgPush.getId()));
        return RespResult.buildWith(success);
    }

    @Override
    public RespResult getMsgPush(FindMsgPushParam param) {
        //MsgPush msgPush = this.getById(msgPushParam.getId());
        MsgPush msgPush = this.getOne(Wrappers.<MsgPush>lambdaQuery()
                //通过select设置待查询的column列表
                .select(MsgPush::getId, MsgPush::getMsgContent, MsgPush::getPushType, MsgPush::getPushResult)
                //设置查询where条件
                .eq(ObjectUtils.isNotNull(param.getId()), MsgPush::getId, param.getId()));
        return RespResult.buildSuccessData(msgPush);
    }

    @Override
    public RespResult deleteMsgPush(Long id) {
        //根据ID删除记录
        Boolean success = this.removeById(id);
        //Boolean success = this.remove(Wrappers.<MsgPush>lambdaQuery());
        return RespResult.buildWith(success);
    }

    /**
     * 转换MsgPush对象
     *
     * @param msgPushParam
     * @return
     */
    private MsgPush convertMsgPush(MsgPushParam msgPushParam) {
        //转换msgPush对象
        MsgPush msgPush = new MsgPush();
        msgPush.setPushType(msgPushParam.getPushType());
        msgPush.setMsgContent(msgPushParam.getMsgContent());
        msgPush.setPushResult(RespCodeEnum.SUCCESS.getCode());
        msgPush.setCreateTime(LocalDateTime.now());
        msgPush.setUpdateTime(LocalDateTime.now());
        return msgPush;
    }

    /**
     * 转换MsgTarget对象列表
     *
     * @param msgPush
     * @param msgPushParam
     * @return
     */
    private List<MsgTarget> convertMsgTargetList(MsgPush msgPush, MsgPushParam msgPushParam) {
        return msgPushParam.getTargetTopic().stream()
                .map(targetTopic -> {
                    MsgTarget msgTarget = new MsgTarget();
                    msgTarget.setPushId(msgPush.getId());
                    msgTarget.setTargetTopic(targetTopic);
                    msgTarget.setPushResult(RespCodeEnum.SUCCESS.getCode());
                    msgTarget.setQos(msgPushParam.getQos());
                    msgTarget.setUpdateTime(LocalDateTime.now());
                    msgTarget.setCreateTime(LocalDateTime.now());
                    return msgTarget;
                }).collect(Collectors.toList());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗小爬EX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值