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