Springboot 整合 mybatisplus

springboot整合mybatisplus

application.yml

這里以TDengine時(shí)序數(shù)據(jù)庫為例

spring:
  datasource:
    driver-class-name: com.taosdata.jdbc.TSDBDriver
#    driver-class-name: com.taosdata.jdbc.rs.RestfulDriver
#    url: jdbc:TAOS-RS://um.tdengine.com:6041/test?timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8
    url: jdbc:TAOS://um.tdengine.com:6030/test?timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8
    username: root
    password: taosdata

    hikari:
      pool-name: HikariPool
      # 最小空閑鏈接數(shù)
      minimum-idle: 32
      # 空閑連接存活最大時(shí)間 默認(rèn) 600000(10分鐘)
      idle-timeout: 0
      # 連接池最大連接數(shù)义辕,默認(rèn) 10
      maximum-pool-size: 128
      # 如果池?zé)o法成功初始化連接区端,則此屬性控制池是否將fail fast
      initialization-fail-timeout: -1
      # 數(shù)據(jù)庫連接超時(shí)時(shí)間舶斧,默認(rèn)30s
      connection-timeout: 60000
      # 此屬性控制池中連接的最大生命周期乔煞,值0表示無限生命周期寥院,默認(rèn)1800000即30分鐘
      max-lifetime: 0
      # 連接檢查 。 mysql 使用的 為 select 1  tdengine 特有語句 select server_status()
      connection-test-query: select server_status()

mybatis-plus:
  configuration:
    # 控制臺(tái)打印sql
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 數(shù)據(jù)庫下劃線字段 與 實(shí)體中的駝峰屬性映射(false颗品,手動(dòng)設(shè)置映射朽缎,推薦用 resultMap)
    # mybatis的駝峰法映射并不是嚴(yán)格限制的駝峰法語法,具體來說翰守,對(duì)應(yīng)“aa_bb”字段孵奶,其既可以匹配上“aaBb”屬性,也可以匹配上“Aabb”屬性蜡峰。這一點(diǎn)在日常寫代碼時(shí)需要注意下了袁。
    map-underscore-to-camel-case: false
  # mapper.xml所在目錄
  mapper-locations: classpath:/mapper/**/*.xml

logging:
  level:
    com.taosdata.example.mybatisplusdemo.mapper: debug

maven依賴

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

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

配置分頁插件

MybatisPlusInterceptor

package com.yomahub.liteflow.example.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {

    /**
     * 新的分頁插件,一緩和二緩遵循mybatis的規(guī)則,需要設(shè)置 MybatisConfiguration#useDeprecatedExecutor = false 避免緩存出現(xiàn)問題(該屬性會(huì)在舊插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加自動(dòng)分頁插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        // 自定義配置
        return configuration -> {

        };
    }
}

配置字段自動(dòng)填充

針對(duì) createTime、updateTime湿颅、createBy载绿、updateBy

這里指定時(shí)間為 13位時(shí)間戳 Long類型, 時(shí)區(qū) +8

package com.yomahub.liteflow.example.config;

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

import java.time.LocalDateTime;
import java.time.ZoneOffset;

/**
 * @description 配置 字段自動(dòng)填充油航,針對(duì) createTime崭庸、updateTime
 * @author peizhao.ma
 * @date 2022-07-13
 */
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(), Long.class); // 起始版本 3.3.3(推薦)
//        // 或者
//        this.strictInsertFill(metaObject, "createTime", Long.class, LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()); // 起始版本 3.3.0(推薦使用)

//        // 或者
//        this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 該方法有bug)
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(), Long.class); // 起始版本 3.3.3(推薦)

        // 或者
//        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推薦)

        // 或者
//        this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 該方法有bug)
    }
}

自動(dòng)填充注解

標(biāo)注什么時(shí)候自動(dòng)填充转唉。 如 INSERT 诅蝶、 UPDATE 時(shí)填充對(duì)應(yīng)字段

package com.yomahub.liteflow.example.pojo.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;

public class BaseEntity {

    @TableField(value = "create_by", fill = FieldFill.INSERT)
    private String createBy;

    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Long createTime;

    @TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
    private String updateBy;

    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    private Long updateTime;

}

配置實(shí)體

標(biāo)注表對(duì)應(yīng)的實(shí)體

復(fù)合組件無法使用@TableId標(biāo)注急侥。 主鍵id默認(rèn)使用雪花id

package com.yomahub.liteflow.example.pojo.entity;


import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;

@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName("rule_node")
public class RuleNode extends BaseEntity{

    @TableId
    private Long id;

    @TableField("node_uid")
    private String nodeUid;

    @TableField("node_name")
    private String nodeName;

    @TableField("node_type")
    private Byte nodeType;

    @TableField("script")
    private String script;

    @TableField("script_type")
    private Byte scriptType;

    @TableField("clazz")
    private String clazz;

    @TableField("script_file_address")
    private String scriptFileAddress;

    @TableField("service_uid")
    private String serviceUid;
}

配置mapper

繼承BaseMapper

package com.yomahub.liteflow.example.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yomahub.liteflow.example.pojo.entity.RuleNode;

public interface RuleNodeMapper extends BaseMapper<RuleNode> {
}

配置service

繼承IService接口

package com.yomahub.liteflow.example.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yomahub.liteflow.example.pojo.dto.NodeAddDTO;
import com.yomahub.liteflow.example.pojo.dto.NodeQueryDTO;
import com.yomahub.liteflow.example.pojo.dto.NodeUpdateDTO;
import com.yomahub.liteflow.example.pojo.entity.RuleNode;
import com.yomahub.liteflow.example.pojo.vo.PageVO;

import java.util.List;

public interface RuleNodeService extends IService<RuleNode>{


    boolean save(NodeAddDTO dto);

    PageVO<RuleNode> pageNode(NodeQueryDTO dto);

    boolean update(NodeUpdateDTO dto);

    boolean deleteById(Long nodeId);

    boolean deleteBatchByIds(List<Long> ids);
}

繼承IService實(shí)現(xiàn)類 ServiceImpl<RuleNodeMapper, RuleNode>

package com.yomahub.liteflow.example.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yomahub.liteflow.example.config.LiteServiceConfig;
import com.yomahub.liteflow.example.exception.ServiceException;
import com.yomahub.liteflow.example.mapper.RuleNodeChainMapper;
import com.yomahub.liteflow.example.pojo.dto.NodeAddDTO;
import com.yomahub.liteflow.example.pojo.dto.NodeQueryDTO;
import com.yomahub.liteflow.example.pojo.dto.NodeUpdateDTO;
import com.yomahub.liteflow.example.pojo.entity.RuleNode;
import com.yomahub.liteflow.example.mapper.RuleNodeMapper;
import com.yomahub.liteflow.example.pojo.entity.RuleNodeChain;
import com.yomahub.liteflow.example.pojo.vo.PageVO;
import com.yomahub.liteflow.example.service.RuleNodeService;
import com.yomahub.liteflow.example.service.ScriptService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class RuleNodeServiceImpl extends ServiceImpl<RuleNodeMapper, RuleNode> implements RuleNodeService {

    @Resource
    private LiteServiceConfig LiteServiceConfig;

    @Resource
    private RuleNodeChainMapper ruleNodeChainMapper;

    @Resource
    private ScriptService scriptService;

    @Transactional
    @Override
    public boolean save(NodeAddDTO dto) {
        RuleNodeMapper ruleNodeMapper = this.getBaseMapper();

        // 檢查是否存在該規(guī)則節(jié)點(diǎn)名稱
        String nodeName = dto.getNodeName();
        LambdaQueryWrapper<RuleNode> wrapper = new QueryWrapper<RuleNode>().lambda()
                .eq(!ObjectUtils.isEmpty(dto.getNodeUid()), RuleNode::getNodeUid, dto.getNodeUid())
                .or()
                .eq(RuleNode::getNodeName, nodeName);
        RuleNode node = ruleNodeMapper.selectOne(wrapper);

        if(!ObjectUtils.isEmpty(node)){
            throw new ServiceException("node name 已經(jīng)存在");
        }

        RuleNode saveNode = BeanUtil.copyProperties(dto, RuleNode.class);
        // node節(jié)點(diǎn)需要以字母開頭尾抑,且名字中不能包含中劃線-,因?yàn)?是EL中的減號(hào)熬粗,才能通過腳本編譯搀玖,如 node13078cabb0ed4ff89729aeb12492fcf1
        saveNode.setNodeUid("node" + UUID.randomUUID().toString().replace("-", ""));
        saveNode.setServiceUid(LiteServiceConfig.getServiceUid());
        int rows = ruleNodeMapper.insert(saveNode);
        if(rows > 0){
            scriptService.loadNodesAndChains();
        }
        return rows > 0;
    }

    @Override
    public PageVO<RuleNode> pageNode(NodeQueryDTO dto) {

        RuleNodeMapper ruleNodeMapper = this.getBaseMapper();
        IPage<RuleNode> page = new PageDTO<>(dto.getPageNum(), dto.getPageSize());

        LambdaQueryWrapper<RuleNode> wrapper = new QueryWrapper<RuleNode>().lambda()
                .eq(!ObjectUtils.isEmpty(dto.getNodeName()), RuleNode::getNodeName, dto.getNodeName())
                .eq(!ObjectUtils.isEmpty(dto.getNodeType()), RuleNode::getNodeType, dto.getNodeType())
                .eq(!ObjectUtils.isEmpty(dto.getNodeUid()), RuleNode::getNodeUid, dto.getNodeUid());

        IPage<RuleNode> pageResult = ruleNodeMapper.selectPage(page, wrapper);

        return new PageVO<>(pageResult.getTotal(), pageResult.getRecords());
    }

    @Transactional
    @Override
    public boolean update(NodeUpdateDTO dto) {

        RuleNodeMapper ruleNodeMapper = this.getBaseMapper();

        // 更新前余境,先檢查是否存在該node
        LambdaQueryWrapper<RuleNode> wrapper = new QueryWrapper<RuleNode>().lambda()
                        .eq(RuleNode::getId, dto.getId());
        RuleNode node = ruleNodeMapper.selectOne(wrapper);

        if(ObjectUtils.isEmpty(node)){
            throw new ServiceException("當(dāng)前要修改的節(jié)點(diǎn):<" + dto.getNodeName() + "> 不存在");
        }

        // 存在則進(jìn)行修改
        RuleNode updateNode = BeanUtil.copyProperties(dto, RuleNode.class);
        int rows = ruleNodeMapper.updateById(updateNode);
        if(rows > 0){
            scriptService.loadNodesAndChains();
        }
        return rows > 0;
    }

    @Override
    public boolean deleteById(Long nodeId) {

        // 檢查節(jié)點(diǎn)是否被關(guān)聯(lián)
        LambdaQueryWrapper<RuleNodeChain> wrapper = new QueryWrapper<RuleNodeChain>().lambda()
                .eq(RuleNodeChain::getNodeId, nodeId);
        Long relatedRows = ruleNodeChainMapper.selectCount(wrapper);
        if(relatedRows > 0){
            throw new ServiceException("節(jié)點(diǎn)" + nodeId + "已關(guān)聯(lián)規(guī)則鏈驻呐,無法刪除");
        }

        // 沒被關(guān)聯(lián),則直接刪除
        RuleNodeMapper ruleNodeMapper = this.getBaseMapper();
        int rows = ruleNodeMapper.deleteById(nodeId);
        if(rows > 0){
            scriptService.loadNodesAndChains();
        }
        return rows > 0;
    }

    @Override
    public boolean deleteBatchByIds(List<Long> ids) {

        // 檢查節(jié)點(diǎn)是否被關(guān)聯(lián)
        LambdaQueryWrapper<RuleNodeChain> wrapper = new QueryWrapper<RuleNodeChain>().lambda()
                .in(RuleNodeChain::getNodeId, ids);
        List<RuleNodeChain> list = ruleNodeChainMapper.selectList(wrapper);
        if(!ObjectUtils.isEmpty(list)){
            List<Long> relatedNode = list.stream().map(RuleNodeChain::getNodeId).distinct().collect(Collectors.toList());
            throw new ServiceException("節(jié)點(diǎn)" + relatedNode.toString() + "已關(guān)聯(lián)規(guī)則鏈芳来,無法刪除");
        }

        // 沒被關(guān)聯(lián)含末,則直接刪除
        RuleNodeMapper ruleNodeMapper = this.getBaseMapper();
        int rows = ruleNodeMapper.deleteBatchIds(ids);
        if(rows > 0){
            scriptService.loadNodesAndChains();
        }
        return rows > 0;
    }
}

mapper接口掃描/注入

在 啟動(dòng)類 上加@MapperScan注解進(jìn)行mapper接口掃描

在 mapper接口 上加 @Mapper注解

@SpringBootApplication
@MapperScan("com.yomahub.liteflow.example.mapper")
public class LiteflowExampleApplication {

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

}

參考資料:

[1] 官網(wǎng) https://baomidou.com/

[2] 尚硅谷2022 mybatisplus

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市即舌,隨后出現(xiàn)的幾起案子佣盒,更是在濱河造成了極大的恐慌,老刑警劉巖顽聂,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肥惭,死亡現(xiàn)場離奇詭異,居然都是意外死亡紊搪,警方通過查閱死者的電腦和手機(jī)蜜葱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耀石,“玉大人牵囤,你說我怎么就攤上這事≈臀埃” “怎么了揭鳞?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長梆奈。 經(jīng)常有香客問我野崇,道長,這世上最難降的妖魔是什么亩钟? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任乓梨,我火速辦了婚禮,結(jié)果婚禮上径荔,老公的妹妹穿的比我還像新娘督禽。我一直安慰自己,他們只是感情好总处,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布狈惫。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胧谈。 梳的紋絲不亂的頭發(fā)上忆肾,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音菱肖,去河邊找鬼客冈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛稳强,可吹牛的內(nèi)容都是我干的场仲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼退疫,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼渠缕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起褒繁,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤亦鳞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后棒坏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體燕差,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年坝冕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了徒探。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡徽诲,死狀恐怖刹帕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谎替,我是刑警寧澤偷溺,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站钱贯,受9級(jí)特大地震影響挫掏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜秩命,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一尉共、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧弃锐,春花似錦袄友、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春鸠按,著一層夾襖步出監(jiān)牢的瞬間礼搁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國打工目尖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留馒吴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓瑟曲,卻偏偏與公主長得像饮戳,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子测蹲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容