fix bugs
This commit is contained in:
64
blade-starter-mybatis/pom.xml
Normal file
64
blade-starter-mybatis/pom.xml
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>BladeX-Tool</artifactId>
|
||||
<groupId>org.springblade</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>blade-starter-mybatis</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>${project.parent.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!--Mybatis-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-spring</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-typehandlers-jsr310</artifactId>
|
||||
</dependency>
|
||||
<!--Jdbc-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>tomcat-jdbc</artifactId>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- Druid -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid</artifactId>
|
||||
</dependency>
|
||||
<!--Blade-->
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-auth</artifactId>
|
||||
</dependency>
|
||||
<!-- Auto -->
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-auto</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
|
||||
/**
|
||||
* mybatisplus自定义填充
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
public class BladeMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.base;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springblade.core.tool.utils.DateUtil;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 基础实体类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
public class BaseEntity implements Serializable {
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@Schema(description = "主键id")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@Schema(description = "创建人")
|
||||
private Long createUser;
|
||||
|
||||
/**
|
||||
* 创建部门
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@Schema(description = "创建部门")
|
||||
private Long createDept;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@Schema(description = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@Schema(description = "更新人")
|
||||
private Long updateUser;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@Schema(description = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 状态[1:正常]
|
||||
*/
|
||||
@Schema(description = "业务状态")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 状态[0:未删除,1:删除]
|
||||
*/
|
||||
@TableLogic
|
||||
@Schema(description = "是否已删除")
|
||||
private Integer isDeleted;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 基础业务接口
|
||||
*
|
||||
* @param <T>
|
||||
* @author Chill
|
||||
*/
|
||||
public interface BaseService<T> extends IService<T> {
|
||||
|
||||
/**
|
||||
* 逻辑删除
|
||||
*
|
||||
* @param ids id集合
|
||||
* @return
|
||||
*/
|
||||
boolean deleteLogic(@NotEmpty List<Long> ids);
|
||||
|
||||
/**
|
||||
* 变更状态
|
||||
*
|
||||
* @param ids id集合
|
||||
* @param status 状态值
|
||||
* @return
|
||||
*/
|
||||
boolean changeStatus(@NotEmpty List<Long> ids, Integer status);
|
||||
|
||||
/**
|
||||
* 判断是否有字段重复
|
||||
*
|
||||
* @param field 字段
|
||||
* @param value 值
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isFieldDuplicate(SFunction<T, ?> field, Object value);
|
||||
|
||||
/**
|
||||
* 判断是否有字段重复
|
||||
*
|
||||
* @param field 字段
|
||||
* @param value 值
|
||||
* @param excludedId 排除的id
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isFieldDuplicate(SFunction<T, ?> field, Object value, Long excludedId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springblade.core.secure.BladeUser;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tool.constant.BladeConstant;
|
||||
import org.springblade.core.tool.utils.*;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 业务封装基础类
|
||||
*
|
||||
* @param <M> mapper
|
||||
* @param <T> model
|
||||
* @author Chill
|
||||
*/
|
||||
@Validated
|
||||
public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseEntity> extends ServiceImpl<M, T> implements BaseService<T> {
|
||||
|
||||
@Override
|
||||
public boolean save(T entity) {
|
||||
this.resolveEntity(entity);
|
||||
return super.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveBatch(Collection<T> entityList, int batchSize) {
|
||||
entityList.forEach(this::resolveEntity);
|
||||
return super.saveBatch(entityList, batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateById(T entity) {
|
||||
this.resolveEntity(entity);
|
||||
return super.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateBatchById(Collection<T> entityList, int batchSize) {
|
||||
entityList.forEach(this::resolveEntity);
|
||||
return super.updateBatchById(entityList, batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveOrUpdate(T entity) {
|
||||
if (entity.getId() == null) {
|
||||
return this.save(entity);
|
||||
} else {
|
||||
return this.updateById(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
|
||||
entityList.forEach(this::resolveEntity);
|
||||
return super.saveOrUpdateBatch(entityList, batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteLogic(@NotEmpty List<Long> ids) {
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
List<T> list = new ArrayList<>();
|
||||
ids.forEach(id -> {
|
||||
T entity = BeanUtil.newInstance(currentModelClass());
|
||||
if (user != null) {
|
||||
entity.setUpdateUser(user.getUserId());
|
||||
}
|
||||
entity.setUpdateTime(DateUtil.now());
|
||||
entity.setId(id);
|
||||
list.add(entity);
|
||||
});
|
||||
return super.updateBatchById(list) && super.removeByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeStatus(@NotEmpty List<Long> ids, Integer status) {
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
List<T> list = new ArrayList<>();
|
||||
ids.forEach(id -> {
|
||||
T entity = BeanUtil.newInstance(currentModelClass());
|
||||
if (user != null) {
|
||||
entity.setUpdateUser(user.getUserId());
|
||||
}
|
||||
entity.setUpdateTime(DateUtil.now());
|
||||
entity.setId(id);
|
||||
entity.setStatus(status);
|
||||
list.add(entity);
|
||||
});
|
||||
return super.updateBatchById(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFieldDuplicate(SFunction<T, ?> field, Object value) {
|
||||
LambdaQueryWrapper<T> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(field, value);
|
||||
return super.count(queryWrapper) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFieldDuplicate(SFunction<T, ?> field, Object value, Long excludedId) {
|
||||
LambdaQueryWrapper<T> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(field, value);
|
||||
if (excludedId != null) {
|
||||
queryWrapper.ne(T::getId, excludedId);
|
||||
}
|
||||
return super.count(queryWrapper) > 0;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private void resolveEntity(T entity) {
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
Date now = DateUtil.now();
|
||||
if (entity.getId() == null) {
|
||||
// 处理新增逻辑
|
||||
if (user != null) {
|
||||
entity.setCreateUser(user.getUserId());
|
||||
entity.setCreateDept(Func.firstLong(user.getDeptId()));
|
||||
entity.setUpdateUser(user.getUserId());
|
||||
}
|
||||
if (entity.getStatus() == null) {
|
||||
entity.setStatus(BladeConstant.DB_STATUS_NORMAL);
|
||||
}
|
||||
entity.setCreateTime(now);
|
||||
} else if (user != null) {
|
||||
// 处理修改逻辑
|
||||
entity.setUpdateUser(user.getUserId());
|
||||
}
|
||||
// 处理通用逻辑
|
||||
entity.setUpdateTime(now);
|
||||
entity.setIsDeleted(BladeConstant.DB_NOT_DELETED);
|
||||
// 处理多租户逻辑,若字段值为空,则不进行操作
|
||||
Field field = ReflectUtil.getField(entity.getClass(), BladeConstant.DB_TENANT_KEY);
|
||||
if (ObjectUtil.isNotEmpty(field)) {
|
||||
Method getTenantId = ClassUtil.getMethod(entity.getClass(), BladeConstant.DB_TENANT_KEY_GET_METHOD);
|
||||
String tenantId = String.valueOf(getTenantId.invoke(entity));
|
||||
if (ObjectUtil.isEmpty(tenantId)) {
|
||||
Method setTenantId = ClassUtil.getMethod(entity.getClass(), BladeConstant.DB_TENANT_KEY_SET_METHOD, String.class);
|
||||
setTenantId.invoke(entity, (Object) null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.base;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springblade.core.tool.utils.DateUtil;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 自定义业务实体类(推荐自行修改拓展并用于特定业务模块)
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
public class BizEntity implements Serializable {
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@Schema(description = "主键id")
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@Schema(description = "租户ID")
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@Schema(description = "创建人")
|
||||
private Long createUser;
|
||||
|
||||
/**
|
||||
* 创建部门
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@Schema(description = "创建部门")
|
||||
private Long createDept;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@Schema(description = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@Schema(description = "更新人")
|
||||
private Long updateUser;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@DateTimeFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@JsonFormat(pattern = DateUtil.PATTERN_DATETIME)
|
||||
@Schema(description = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 状态[1:正常]
|
||||
*/
|
||||
@Schema(description = "业务状态")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 状态[0:未删除,1:删除]
|
||||
*/
|
||||
@TableLogic
|
||||
@Schema(description = "是否已删除")
|
||||
private Integer isDeleted;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自定义业务接口(推荐自行修改拓展并用于特定业务模块)
|
||||
*
|
||||
* @param <T>
|
||||
* @author Chill
|
||||
*/
|
||||
public interface BizService<T> extends IService<T> {
|
||||
|
||||
/**
|
||||
* 逻辑删除
|
||||
*
|
||||
* @param ids id集合
|
||||
* @return
|
||||
*/
|
||||
boolean deleteLogic(@NotEmpty List<Long> ids);
|
||||
|
||||
/**
|
||||
* 变更状态
|
||||
*
|
||||
* @param ids id集合
|
||||
* @param status 状态值
|
||||
* @return
|
||||
*/
|
||||
boolean changeStatus(@NotEmpty List<Long> ids, Integer status);
|
||||
|
||||
/**
|
||||
* 判断是否有字段重复
|
||||
*
|
||||
* @param field 字段
|
||||
* @param value 值
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isFieldDuplicate(SFunction<T, ?> field, Object value);
|
||||
|
||||
/**
|
||||
* 判断是否有字段重复
|
||||
*
|
||||
* @param field 字段
|
||||
* @param value 值
|
||||
* @param excludedId 排除的id
|
||||
* @return boolean
|
||||
*/
|
||||
boolean isFieldDuplicate(SFunction<T, ?> field, Object value, Long excludedId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springblade.core.secure.BladeUser;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tool.constant.BladeConstant;
|
||||
import org.springblade.core.tool.utils.*;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自定义业务封装基础类(推荐自行修改拓展并用于特定业务模块)
|
||||
*
|
||||
* @param <M> mapper
|
||||
* @param <T> model
|
||||
* @author Chill
|
||||
*/
|
||||
@Validated
|
||||
public class BizServiceImpl<M extends BaseMapper<T>, T extends BizEntity> extends ServiceImpl<M, T> implements BizService<T> {
|
||||
|
||||
@Override
|
||||
public boolean save(T entity) {
|
||||
this.resolveEntity(entity);
|
||||
return super.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveBatch(Collection<T> entityList, int batchSize) {
|
||||
entityList.forEach(this::resolveEntity);
|
||||
return super.saveBatch(entityList, batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateById(T entity) {
|
||||
this.resolveEntity(entity);
|
||||
return super.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateBatchById(Collection<T> entityList, int batchSize) {
|
||||
entityList.forEach(this::resolveEntity);
|
||||
return super.updateBatchById(entityList, batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveOrUpdate(T entity) {
|
||||
if (entity.getId() == null) {
|
||||
return this.save(entity);
|
||||
} else {
|
||||
return this.updateById(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
|
||||
entityList.forEach(this::resolveEntity);
|
||||
return super.saveOrUpdateBatch(entityList, batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteLogic(@NotEmpty List<Long> ids) {
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
List<T> list = new ArrayList<>();
|
||||
ids.forEach(id -> {
|
||||
T entity = BeanUtil.newInstance(currentModelClass());
|
||||
if (user != null) {
|
||||
entity.setUpdateUser(user.getUserId());
|
||||
}
|
||||
entity.setUpdateTime(DateUtil.now());
|
||||
entity.setId(id);
|
||||
list.add(entity);
|
||||
});
|
||||
return super.updateBatchById(list) && super.removeByIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeStatus(@NotEmpty List<Long> ids, Integer status) {
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
List<T> list = new ArrayList<>();
|
||||
ids.forEach(id -> {
|
||||
T entity = BeanUtil.newInstance(currentModelClass());
|
||||
if (user != null) {
|
||||
entity.setUpdateUser(user.getUserId());
|
||||
}
|
||||
entity.setUpdateTime(DateUtil.now());
|
||||
entity.setId(id);
|
||||
entity.setStatus(status);
|
||||
list.add(entity);
|
||||
});
|
||||
return super.updateBatchById(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFieldDuplicate(SFunction<T, ?> field, Object value) {
|
||||
LambdaQueryWrapper<T> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(field, value);
|
||||
return super.count(queryWrapper) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFieldDuplicate(SFunction<T, ?> field, Object value, Long excludedId) {
|
||||
LambdaQueryWrapper<T> queryWrapper = Wrappers.lambdaQuery();
|
||||
queryWrapper.eq(field, value);
|
||||
if (excludedId != null) {
|
||||
queryWrapper.ne(T::getId, excludedId);
|
||||
}
|
||||
return super.count(queryWrapper) > 0;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private void resolveEntity(T entity) {
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
Date now = DateUtil.now();
|
||||
if (entity.getId() == null) {
|
||||
// 处理新增逻辑
|
||||
if (user != null) {
|
||||
entity.setCreateUser(user.getUserId());
|
||||
entity.setCreateDept(Func.firstLong(user.getDeptId()));
|
||||
entity.setUpdateUser(user.getUserId());
|
||||
}
|
||||
if (entity.getStatus() == null) {
|
||||
entity.setStatus(BladeConstant.DB_STATUS_NORMAL);
|
||||
}
|
||||
entity.setCreateTime(now);
|
||||
} else if (user != null) {
|
||||
// 处理修改逻辑
|
||||
entity.setUpdateUser(user.getUserId());
|
||||
}
|
||||
// 处理通用逻辑
|
||||
entity.setUpdateTime(now);
|
||||
entity.setIsDeleted(BladeConstant.DB_NOT_DELETED);
|
||||
// 处理多租户逻辑,若字段值为空,则不进行操作
|
||||
Field field = ReflectUtil.getField(entity.getClass(), BladeConstant.DB_TENANT_KEY);
|
||||
if (ObjectUtil.isNotEmpty(field)) {
|
||||
Method getTenantId = ClassUtil.getMethod(entity.getClass(), BladeConstant.DB_TENANT_KEY_GET_METHOD);
|
||||
String tenantId = String.valueOf(getTenantId.invoke(entity));
|
||||
if (ObjectUtil.isEmpty(tenantId)) {
|
||||
Method setTenantId = ClassUtil.getMethod(entity.getClass(), BladeConstant.DB_TENANT_KEY_SET_METHOD, String.class);
|
||||
setTenantId.invoke(entity, (Object) null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.StringValue;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springblade.core.launch.props.BladePropertySource;
|
||||
import org.springblade.core.mp.injector.BladeSqlInjector;
|
||||
import org.springblade.core.mp.intercept.QueryInterceptor;
|
||||
import org.springblade.core.mp.plugins.BladePaginationInterceptor;
|
||||
import org.springblade.core.mp.plugins.SqlLogInterceptor;
|
||||
import org.springblade.core.mp.props.MybatisPlusProperties;
|
||||
import org.springblade.core.mp.resolver.PageArgumentResolver;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tool.constant.BladeConstant;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.ObjectUtil;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* mybatis-plus 配置
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@AllArgsConstructor
|
||||
@MapperScan("org.springblade.**.mapper.**")
|
||||
@EnableConfigurationProperties(MybatisPlusProperties.class)
|
||||
@BladePropertySource(value = "classpath:/blade-mybatis.yml")
|
||||
public class MybatisPlusConfiguration implements WebMvcConfigurer {
|
||||
|
||||
/**
|
||||
* 租户拦截器
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(TenantLineInnerInterceptor.class)
|
||||
public TenantLineInnerInterceptor tenantLineInnerInterceptor() {
|
||||
return new TenantLineInnerInterceptor(new TenantLineHandler() {
|
||||
@Override
|
||||
public Expression getTenantId() {
|
||||
return new StringValue(Func.toStr(AuthUtil.getTenantId(), BladeConstant.ADMIN_TENANT_ID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ignoreTable(String tableName) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* mybatis-plus 拦截器集合
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MybatisPlusInterceptor.class)
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor(ObjectProvider<QueryInterceptor[]> queryInterceptors,
|
||||
TenantLineInnerInterceptor tenantLineInnerInterceptor,
|
||||
MybatisPlusProperties mybatisPlusProperties) {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
// 配置租户拦截器
|
||||
if (mybatisPlusProperties.getTenantMode()) {
|
||||
interceptor.addInnerInterceptor(tenantLineInnerInterceptor);
|
||||
}
|
||||
// 配置分页拦截器
|
||||
BladePaginationInterceptor paginationInterceptor = new BladePaginationInterceptor();
|
||||
// 配置自定义查询拦截器
|
||||
QueryInterceptor[] queryInterceptorArray = queryInterceptors.getIfAvailable();
|
||||
if (ObjectUtil.isNotEmpty(queryInterceptorArray)) {
|
||||
AnnotationAwareOrderComparator.sort(queryInterceptorArray);
|
||||
paginationInterceptor.setQueryInterceptors(queryInterceptorArray);
|
||||
}
|
||||
paginationInterceptor.setMaxLimit(mybatisPlusProperties.getPageLimit());
|
||||
paginationInterceptor.setOverflow(mybatisPlusProperties.getOverflow());
|
||||
paginationInterceptor.setOptimizeJoin(mybatisPlusProperties.getOptimizeJoin());
|
||||
interceptor.addInnerInterceptor(paginationInterceptor);
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* sql 日志
|
||||
*/
|
||||
@Bean
|
||||
public SqlLogInterceptor sqlLogInterceptor(MybatisPlusProperties mybatisPlusProperties) {
|
||||
return new SqlLogInterceptor(mybatisPlusProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* sql 注入
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ISqlInjector.class)
|
||||
public ISqlInjector sqlInjector() {
|
||||
return new BladeSqlInjector();
|
||||
}
|
||||
|
||||
/**
|
||||
* page 解析器
|
||||
*/
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.add(new PageArgumentResolver());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.mp.injector;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
||||
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
|
||||
import org.springblade.core.mp.injector.methods.InsertIgnore;
|
||||
import org.springblade.core.mp.injector.methods.Replace;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自定义的 sql 注入
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public class BladeSqlInjector extends DefaultSqlInjector {
|
||||
|
||||
@Override
|
||||
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
|
||||
List<AbstractMethod> methodList = new ArrayList<>();
|
||||
methodList.add(new InsertIgnore());
|
||||
methodList.add(new Replace());
|
||||
methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
|
||||
methodList.addAll(super.getMethodList(mapperClass, tableInfo));
|
||||
return Collections.unmodifiableList(methodList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.mp.injector;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 扩展的自定义方法
|
||||
*
|
||||
* AbstractInsertMethod
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum BladeSqlMethod {
|
||||
|
||||
/**
|
||||
* 插入如果中已经存在相同的记录,则忽略当前新数据
|
||||
*/
|
||||
INSERT_IGNORE_ONE("insertIgnore", "插入一条数据(选择字段插入)", "<script>\nINSERT IGNORE INTO %s %s VALUES %s\n</script>"),
|
||||
|
||||
/**
|
||||
* 表示插入替换数据,需求表中有PrimaryKey,或者unique索引,如果数据库已经存在数据,则用新数据替换,如果没有数据效果则和insert into一样;
|
||||
*/
|
||||
REPLACE_ONE("replace", "插入一条数据(选择字段插入)", "<script>\nREPLACE INTO %s %s VALUES %s\n</script>");
|
||||
|
||||
private final String method;
|
||||
private final String desc;
|
||||
private final String sql;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.mp.injector.methods;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
|
||||
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
|
||||
import org.apache.ibatis.executor.keygen.KeyGenerator;
|
||||
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.SqlSource;
|
||||
import org.springblade.core.mp.injector.BladeSqlMethod;
|
||||
|
||||
/**
|
||||
* 抽象的 插入一条数据(选择字段插入)
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public class AbstractInsertMethod extends AbstractMethod {
|
||||
private final BladeSqlMethod sqlMethod;
|
||||
|
||||
public AbstractInsertMethod(BladeSqlMethod sqlMethod) {
|
||||
super(sqlMethod.getMethod());
|
||||
this.sqlMethod = sqlMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
|
||||
KeyGenerator keyGenerator = new NoKeyGenerator();
|
||||
String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumnMaybeIf(null),
|
||||
LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);
|
||||
String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlPropertyMaybeIf(null),
|
||||
LEFT_BRACKET, RIGHT_BRACKET, null, COMMA);
|
||||
String keyProperty = null;
|
||||
String keyColumn = null;
|
||||
// 表包含主键处理逻辑,如果不包含主键当普通字段处理
|
||||
if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) {
|
||||
if (tableInfo.getIdType() == IdType.AUTO) {
|
||||
// 自增主键
|
||||
keyGenerator = new Jdbc3KeyGenerator();
|
||||
keyProperty = tableInfo.getKeyProperty();
|
||||
keyColumn = tableInfo.getKeyColumn();
|
||||
} else {
|
||||
if (null != tableInfo.getKeySequence()) {
|
||||
keyGenerator = TableInfoHelper.genKeyGenerator(sqlMethod.getMethod(), tableInfo, builderAssistant);
|
||||
keyProperty = tableInfo.getKeyProperty();
|
||||
keyColumn = tableInfo.getKeyColumn();
|
||||
}
|
||||
}
|
||||
}
|
||||
String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
|
||||
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
|
||||
return this.addInsertMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource, keyGenerator, keyProperty, keyColumn);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.mp.injector.methods;
|
||||
|
||||
|
||||
import org.springblade.core.mp.injector.BladeSqlMethod;
|
||||
|
||||
/**
|
||||
* 插入一条数据(选择字段插入)插入如果中已经存在相同的记录,则忽略当前新数据
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public class InsertIgnore extends AbstractInsertMethod {
|
||||
|
||||
public InsertIgnore() {
|
||||
super(BladeSqlMethod.INSERT_IGNORE_ONE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.injector.methods;
|
||||
|
||||
|
||||
import org.springblade.core.mp.injector.BladeSqlMethod;
|
||||
|
||||
/**
|
||||
* 插入一条数据(选择字段插入)
|
||||
* <p>
|
||||
* 表示插入替换数据,需求表中有PrimaryKey,或者unique索引,如果数据库已经存在数据,则用新数据替换,如果没有数据效果则和insert into一样;
|
||||
* </p>
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public class Replace extends AbstractInsertMethod {
|
||||
|
||||
public Replace() {
|
||||
super(BladeSqlMethod.REPLACE_ONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.mp.intercept;
|
||||
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* 自定义 mybatis plus 查询拦截器
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public interface QueryInterceptor extends Ordered {
|
||||
|
||||
/**
|
||||
* 拦截处理
|
||||
*
|
||||
* @param executor
|
||||
* @param ms
|
||||
* @param parameter
|
||||
* @param rowBounds
|
||||
* @param resultHandler
|
||||
* @param boundSql
|
||||
*/
|
||||
void intercept(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql);
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
@Override
|
||||
default int getOrder() {
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自定义的 Mapper
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public interface BladeMapper<T> extends BaseMapper<T> {
|
||||
|
||||
/**
|
||||
* 插入如果中已经存在相同的记录,则忽略当前新数据
|
||||
*
|
||||
* @param entity 实体对象
|
||||
* @return 更改的条数
|
||||
*/
|
||||
int insertIgnore(T entity);
|
||||
|
||||
/**
|
||||
* 表示插入替换数据,需求表中有PrimaryKey,或者unique索引,如果数据库已经存在数据,则用新数据替换,如果没有数据效果则和insert into一样;
|
||||
*
|
||||
* @param entity 实体对象
|
||||
* @return 更改的条数
|
||||
*/
|
||||
int replace(T entity);
|
||||
|
||||
/**
|
||||
* 插入(批量)
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
* @return 成功行数
|
||||
*/
|
||||
int insertBatchSomeColumn(List<T> entityList);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.plugins;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.IDialect;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.OracleDialect;
|
||||
import lombok.Setter;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
import org.springblade.core.mp.intercept.QueryInterceptor;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* 拓展分页拦截器
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Setter
|
||||
public class BladePaginationInterceptor extends PaginationInnerInterceptor {
|
||||
|
||||
/**
|
||||
* 查询拦截器
|
||||
*/
|
||||
private QueryInterceptor[] queryInterceptors;
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
|
||||
QueryInterceptorExecutor.exec(queryInterceptors, executor, ms, parameter, rowBounds, resultHandler, boundSql);
|
||||
return super.willDoQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
|
||||
super.setDialect(autoDialect(executor));
|
||||
super.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动配置分页方言类的逻辑
|
||||
*
|
||||
* @param executor Executor
|
||||
* @return 分页方言类
|
||||
*/
|
||||
@SneakyThrows
|
||||
protected IDialect autoDialect(Executor executor) {
|
||||
// 增加YashanDB方言
|
||||
Connection conn = executor.getTransaction().getConnection();
|
||||
if (conn.getMetaData().getURL().contains(":yasdb:")) {
|
||||
return new OracleDialect();
|
||||
} else {
|
||||
return super.findIDialect(executor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.mp.plugins;
|
||||
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
import org.springblade.core.mp.intercept.QueryInterceptor;
|
||||
import org.springblade.core.tool.utils.ObjectUtil;
|
||||
|
||||
/**
|
||||
* 查询拦截器执行器
|
||||
*
|
||||
* <p>
|
||||
* 目的:抽取此方法是为了后期方便同步更新 {@link BladePaginationInterceptor}
|
||||
* </p>
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public class QueryInterceptorExecutor {
|
||||
|
||||
/**
|
||||
* 执行查询拦截器
|
||||
*/
|
||||
static void exec(QueryInterceptor[] interceptors, Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws Throwable {
|
||||
if (ObjectUtil.isEmpty(interceptors)) {
|
||||
return;
|
||||
}
|
||||
for (QueryInterceptor interceptor : interceptors) {
|
||||
interceptor.intercept(executor, ms, parameter, rowBounds, resultHandler, boundSql);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.plugins;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.filter.FilterChain;
|
||||
import com.alibaba.druid.filter.FilterEventAdapter;
|
||||
import com.alibaba.druid.proxy.jdbc.JdbcParameter;
|
||||
import com.alibaba.druid.proxy.jdbc.ResultSetProxy;
|
||||
import com.alibaba.druid.proxy.jdbc.StatementProxy;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.mp.props.MybatisPlusProperties;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 打印可执行的 sql 日志
|
||||
*
|
||||
* @author L.cm,Chill
|
||||
*/
|
||||
@Slf4j
|
||||
public class SqlLogInterceptor extends FilterEventAdapter {
|
||||
private static final SQLUtils.FormatOption FORMAT_OPTION = new SQLUtils.FormatOption(false, false);
|
||||
|
||||
private static final List<String> SQL_LOG_EXCLUDE = new ArrayList<>(Arrays.asList("ACT_RU_JOB", "ACT_RU_TIMER_JOB"));
|
||||
|
||||
private final MybatisPlusProperties properties;
|
||||
|
||||
public SqlLogInterceptor(MybatisPlusProperties properties) {
|
||||
this.properties = properties;
|
||||
if (properties.getSqlLogExclude().size() > 0) {
|
||||
SQL_LOG_EXCLUDE.addAll(properties.getSqlLogExclude());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void statementExecuteBefore(StatementProxy statement, String sql) {
|
||||
statement.setLastExecuteStartNano();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void statementExecuteBatchBefore(StatementProxy statement) {
|
||||
statement.setLastExecuteStartNano();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void statementExecuteUpdateBefore(StatementProxy statement, String sql) {
|
||||
statement.setLastExecuteStartNano();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void statementExecuteQueryBefore(StatementProxy statement, String sql) {
|
||||
statement.setLastExecuteStartNano();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void statementExecuteAfter(StatementProxy statement, String sql, boolean firstResult) {
|
||||
statement.setLastExecuteTimeNano();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void statementExecuteBatchAfter(StatementProxy statement, int[] result) {
|
||||
statement.setLastExecuteTimeNano();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) {
|
||||
statement.setLastExecuteTimeNano();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) {
|
||||
statement.setLastExecuteTimeNano();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void statement_close(FilterChain chain, StatementProxy statement) {
|
||||
// 是否开启日志
|
||||
if (!properties.getSqlLog()) {
|
||||
chain.statement_close(statement);
|
||||
return;
|
||||
}
|
||||
// 是否开启调试
|
||||
if (!log.isInfoEnabled()) {
|
||||
chain.statement_close(statement);
|
||||
return;
|
||||
}
|
||||
// 打印可执行的 sql
|
||||
String sql = statement.getBatchSql();
|
||||
// sql 为空直接返回
|
||||
if (StringUtil.isEmpty(sql)) {
|
||||
chain.statement_close(statement);
|
||||
return;
|
||||
}
|
||||
// sql 包含排除的关键字直接返回
|
||||
if (excludeSql(sql)) {
|
||||
chain.statement_close(statement);
|
||||
return;
|
||||
}
|
||||
int parametersSize = statement.getParametersSize();
|
||||
List<Object> parameters = new ArrayList<>(parametersSize);
|
||||
for (int i = 0; i < parametersSize; ++i) {
|
||||
// 转换参数,处理 java8 时间
|
||||
parameters.add(getJdbcParameter(statement.getParameter(i)));
|
||||
}
|
||||
String dbType = statement.getConnectionProxy().getDirectDataSource().getDbType();
|
||||
String formattedSql = SQLUtils.format(sql, DbType.of(dbType), parameters, FORMAT_OPTION);
|
||||
printSql(formattedSql, statement);
|
||||
chain.statement_close(statement);
|
||||
}
|
||||
|
||||
private static Object getJdbcParameter(JdbcParameter jdbcParam) {
|
||||
if (jdbcParam == null) {
|
||||
return null;
|
||||
}
|
||||
Object value = jdbcParam.getValue();
|
||||
// 处理 java8 时间
|
||||
if (value instanceof TemporalAccessor) {
|
||||
return value.toString();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static void printSql(String sql, StatementProxy statement) {
|
||||
// 打印 sql
|
||||
String sqlLogger = "\n\n============== Sql Start ==============" +
|
||||
"\nExecute SQL : {}" +
|
||||
"\nExecute Time: {}" +
|
||||
"\n============== Sql End ==============\n";
|
||||
log.info(sqlLogger, sql.trim(), StringUtil.format(statement.getLastExecuteTimeNano()));
|
||||
}
|
||||
|
||||
private static boolean excludeSql(String sql) {
|
||||
// 判断关键字
|
||||
for (String exclude : SQL_LOG_EXCLUDE) {
|
||||
if (sql.contains(exclude)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.props;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MybatisPlus配置类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "blade.mybatis-plus")
|
||||
public class MybatisPlusProperties {
|
||||
|
||||
/**
|
||||
* 开启租户模式
|
||||
*/
|
||||
private Boolean tenantMode = true;
|
||||
|
||||
/**
|
||||
* 开启sql日志
|
||||
*/
|
||||
private Boolean sqlLog = true;
|
||||
|
||||
/**
|
||||
* sql日志忽略打印关键字
|
||||
*/
|
||||
private List<String> sqlLogExclude = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 分页最大数
|
||||
*/
|
||||
private Long pageLimit = 500L;
|
||||
|
||||
/**
|
||||
* 溢出总页数后是否进行处理
|
||||
*/
|
||||
protected Boolean overflow = false;
|
||||
|
||||
/**
|
||||
* join优化
|
||||
*/
|
||||
private Boolean optimizeJoin = false;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.springblade.core.mp.resolver;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.springblade.core.tool.utils.ObjectUtil;
|
||||
import org.springblade.core.tool.utils.StringPool;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
/**
|
||||
* 解决 Mybatis Plus page SQL注入问题
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public class PageArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
private static final String ORDER_ASC = "asc";
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return Page.class.equals(parameter.getParameterType());
|
||||
}
|
||||
|
||||
/**
|
||||
* page 参数解析
|
||||
*
|
||||
* @param parameter MethodParameter
|
||||
* @param mavContainer ModelAndViewContainer
|
||||
* @param request NativeWebRequest
|
||||
* @param binderFactory WebDataBinderFactory
|
||||
* @return 检查后新的page对象
|
||||
*/
|
||||
@Override
|
||||
public Object resolveArgument(@NonNull MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest request, WebDataBinderFactory binderFactory) {
|
||||
// 分页参数 page: 0, size: 10, sort=id%2Cdesc
|
||||
String pageParam = request.getParameter("page");
|
||||
String sizeParam = request.getParameter("size");
|
||||
String[] sortParam = request.getParameterValues("sort");
|
||||
Page<?> page = new Page<>();
|
||||
if (StringUtil.isNotBlank(pageParam)) {
|
||||
page.setCurrent(Long.parseLong(pageParam));
|
||||
}
|
||||
if (StringUtil.isNotBlank(sizeParam)) {
|
||||
page.setSize(Long.parseLong(sizeParam));
|
||||
}
|
||||
if (ObjectUtil.isEmpty(sortParam)) {
|
||||
return page;
|
||||
}
|
||||
for (String param : sortParam) {
|
||||
if (StringUtil.isBlank(param)) {
|
||||
continue;
|
||||
}
|
||||
String[] split = param.split(StringPool.COMMA);
|
||||
// 清理字符串
|
||||
OrderItem orderItem = new OrderItem();
|
||||
orderItem.setColumn(StringUtil.cleanIdentifier(split[0]));
|
||||
orderItem.setAsc(isOrderAsc(split));
|
||||
page.addOrder(orderItem);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
private static boolean isOrderAsc(String[] split) {
|
||||
// 默认 desc
|
||||
if (split.length < 2) {
|
||||
return false;
|
||||
}
|
||||
return ORDER_ASC.equalsIgnoreCase(split[1]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.mp.service;
|
||||
|
||||
import org.springblade.core.mp.base.BaseService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自定义的 Service
|
||||
*
|
||||
* @author L.cm, chill
|
||||
*/
|
||||
public interface BladeService<T> extends BaseService<T> {
|
||||
|
||||
/**
|
||||
* 插入如果中已经存在相同的记录,则忽略当前新数据
|
||||
*
|
||||
* @param entity entity
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean saveIgnore(T entity);
|
||||
|
||||
/**
|
||||
* 表示插入替换数据,需求表中有PrimaryKey,或者unique索引,如果数据库已经存在数据,则用新数据替换,如果没有数据效果则和insert into一样;
|
||||
*
|
||||
* @param entity entity
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean saveReplace(T entity);
|
||||
|
||||
/**
|
||||
* 插入(批量),插入如果中已经存在相同的记录,则忽略当前新数据
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
* @param batchSize 批次大小
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean saveIgnoreBatch(Collection<T> entityList, int batchSize);
|
||||
|
||||
/**
|
||||
* 插入(批量),插入如果中已经存在相同的记录,则忽略当前新数据
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
* @return 是否成功
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
default boolean saveIgnoreBatch(Collection<T> entityList) {
|
||||
return saveIgnoreBatch(entityList, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入(批量),表示插入替换数据,需求表中有PrimaryKey,或者unique索引,如果数据库已经存在数据,则用新数据替换,如果没有数据效果则和insert into一样;
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
* @param batchSize 批次大小
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean saveReplaceBatch(Collection<T> entityList, int batchSize);
|
||||
|
||||
/**
|
||||
* 插入(批量),表示插入替换数据,需求表中有PrimaryKey,或者unique索引,如果数据库已经存在数据,则用新数据替换,如果没有数据效果则和insert into一样;
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
* @return 是否成功
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
default boolean saveReplaceBatch(Collection<T> entityList) {
|
||||
return saveReplaceBatch(entityList, 1000);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
|
||||
package org.springblade.core.mp.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||
import org.springblade.core.mp.base.BaseEntity;
|
||||
import org.springblade.core.mp.base.BaseServiceImpl;
|
||||
import org.springblade.core.mp.injector.BladeSqlMethod;
|
||||
import org.springblade.core.mp.mapper.BladeMapper;
|
||||
import org.springblade.core.mp.service.BladeService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* BladeService 实现类( 泛型:M 是 mapper 对象,T 是实体 , PK 是主键泛型 )
|
||||
*
|
||||
* @author L.cm, chill
|
||||
*/
|
||||
@Validated
|
||||
public class BladeServiceImpl<M extends BladeMapper<T>, T extends BaseEntity> extends BaseServiceImpl<M, T> implements BladeService<T> {
|
||||
|
||||
@Override
|
||||
public boolean saveIgnore(T entity) {
|
||||
return SqlHelper.retBool(baseMapper.insertIgnore(entity));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveReplace(T entity) {
|
||||
return SqlHelper.retBool(baseMapper.replace(entity));
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean saveIgnoreBatch(Collection<T> entityList, int batchSize) {
|
||||
return saveBatch(entityList, batchSize, BladeSqlMethod.INSERT_IGNORE_ONE);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean saveReplaceBatch(Collection<T> entityList, int batchSize) {
|
||||
return saveBatch(entityList, batchSize, BladeSqlMethod.REPLACE_ONE);
|
||||
}
|
||||
|
||||
private boolean saveBatch(Collection<T> entityList, int batchSize, BladeSqlMethod sqlMethod) {
|
||||
String sqlStatement = bladeSqlStatement(sqlMethod);
|
||||
executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 bladeSqlStatement
|
||||
*
|
||||
* @param sqlMethod ignore
|
||||
* @return sql
|
||||
*/
|
||||
protected String bladeSqlStatement(BladeSqlMethod sqlMethod) {
|
||||
return SqlHelper.table(currentModelClass()).getSqlStatement(sqlMethod.getMethod());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.support;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 视图包装基类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public abstract class BaseEntityWrapper<E, V> {
|
||||
|
||||
/**
|
||||
* 单个实体类包装
|
||||
*
|
||||
* @param entity 实体类
|
||||
* @return V
|
||||
*/
|
||||
public abstract V entityVO(E entity);
|
||||
|
||||
/**
|
||||
* 实体类集合包装
|
||||
*
|
||||
* @param list 实体类集合
|
||||
* @return List<V>
|
||||
*/
|
||||
public List<V> listVO(List<E> list) {
|
||||
return list.stream().map(this::entityVO).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页实体类集合包装
|
||||
*
|
||||
* @param pages 分页对象
|
||||
* @return IPage<V>
|
||||
*/
|
||||
public IPage<V> pageVO(IPage<E> pages) {
|
||||
List<V> records = listVO(pages.getRecords());
|
||||
IPage<V> pageVo = new Page<>(pages.getCurrent(), pages.getSize(), pages.getTotal());
|
||||
pageVo.setRecords(records);
|
||||
return pageVo;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.support;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页模型
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
public class BladePage<T> implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 查询数据列表
|
||||
*/
|
||||
private List<T> records = Collections.emptyList();
|
||||
|
||||
/**
|
||||
* 总数
|
||||
*/
|
||||
private long total = 0;
|
||||
/**
|
||||
* 每页显示条数,默认 10
|
||||
*/
|
||||
private long size = 10;
|
||||
|
||||
/**
|
||||
* 当前页
|
||||
*/
|
||||
private long current = 1;
|
||||
|
||||
/**
|
||||
* mybatis-plus分页模型转化
|
||||
*
|
||||
* @param page 分页实体类
|
||||
* @return BladePage<T>
|
||||
*/
|
||||
public static <T> BladePage<T> of(IPage<T> page) {
|
||||
BladePage<T> bladePage = new BladePage<>();
|
||||
bladePage.setRecords(page.getRecords());
|
||||
bladePage.setTotal(page.getTotal());
|
||||
bladePage.setSize(page.getSize());
|
||||
bladePage.setCurrent(page.getCurrent());
|
||||
return bladePage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.support;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
import org.springblade.core.tool.utils.BeanUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 分页工具
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class Condition {
|
||||
|
||||
/**
|
||||
* 转化成mybatis plus中的Page
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @return IPage
|
||||
*/
|
||||
public static <T> IPage<T> getPage(Query query) {
|
||||
Page<T> page = new Page<>(Func.toInt(query.getCurrent(), 1), Func.toInt(query.getSize(), 10));
|
||||
String[] ascArr = Func.toStrArray(query.getAscs());
|
||||
for (String asc : ascArr) {
|
||||
page.addOrder(OrderItem.asc(StringUtil.cleanIdentifier(asc)));
|
||||
}
|
||||
String[] descArr = Func.toStrArray(query.getDescs());
|
||||
for (String desc : descArr) {
|
||||
page.addOrder(OrderItem.desc(StringUtil.cleanIdentifier(desc)));
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转化成mybatis plus中的Page
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @return IPage
|
||||
*/
|
||||
public static <T> IPage<T> getPageDesc(Query query) {
|
||||
Page<T> page = new Page<>(Func.toInt(query.getCurrent(), 1), Func.toInt(query.getSize(), 10));
|
||||
String[] descArr = Func.toStrArray(query.getDescs());
|
||||
for (String desc : descArr) {
|
||||
page.addOrder(OrderItem.desc(StringUtil.cleanIdentifier(desc)));
|
||||
}
|
||||
String[] ascArr = Func.toStrArray(query.getAscs());
|
||||
for (String asc : ascArr) {
|
||||
page.addOrder(OrderItem.asc(StringUtil.cleanIdentifier(asc)));
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取mybatis plus中的QueryWrapper
|
||||
*
|
||||
* @param entity 实体
|
||||
* @param <T> 类型
|
||||
* @return QueryWrapper
|
||||
*/
|
||||
public static <T> QueryWrapper<T> getQueryWrapper(T entity) {
|
||||
return new QueryWrapper<>(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取mybatis plus中的QueryWrapper
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @param clazz 实体类
|
||||
* @param <T> 类型
|
||||
* @return QueryWrapper
|
||||
*/
|
||||
public static <T> QueryWrapper<T> getQueryWrapper(Map<String, Object> query, Class<T> clazz) {
|
||||
Kv exclude = Kv.create().set(TokenConstant.HEADER, TokenConstant.HEADER)
|
||||
.set("current", "current").set("size", "size").set("ascs", "ascs").set("descs", "descs");
|
||||
return getQueryWrapper(query, exclude, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取mybatis plus中的QueryWrapper
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @param exclude 排除的查询条件
|
||||
* @param clazz 实体类
|
||||
* @param <T> 类型
|
||||
* @return QueryWrapper
|
||||
*/
|
||||
public static <T> QueryWrapper<T> getQueryWrapper(Map<String, Object> query, Map<String, Object> exclude, Class<T> clazz) {
|
||||
exclude.forEach((k, v) -> query.remove(k));
|
||||
QueryWrapper<T> qw = new QueryWrapper<>();
|
||||
qw.setEntity(BeanUtil.newInstance(clazz));
|
||||
SqlKeyword.buildCondition(query, qw);
|
||||
return qw;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.support;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 分页工具
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(description = "查询条件")
|
||||
public class Query {
|
||||
|
||||
/**
|
||||
* 当前页
|
||||
*/
|
||||
@Schema(description = "当前页")
|
||||
private Integer current;
|
||||
|
||||
/**
|
||||
* 每页的数量
|
||||
*/
|
||||
@Schema(description = "每页的数量")
|
||||
private Integer size;
|
||||
|
||||
/**
|
||||
* 正排序规则
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
private String ascs;
|
||||
|
||||
/**
|
||||
* 倒排序规则
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
private String descs;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.support;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springblade.core.tool.utils.DateUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringPool;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 定义常用的 sql关键字
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class SqlKeyword {
|
||||
/**
|
||||
* 常规sql字符匹配关键词
|
||||
*/
|
||||
private final static String SQL_REGEX = "(?i)(?<![a-z])('|%|--|insert|delete|select|sleep|count|updatexml|group|union|drop|truncate|alter|grant|execute|exec|xp_cmdshell|call|declare|sql)(?![a-z])";
|
||||
|
||||
/**
|
||||
* 二次匹配防止双写等注入手段
|
||||
*/
|
||||
private final static Pattern PATTERN = Pattern.compile("(?:--|[\"';%]|\\binsert\\b|\\bdelete\\b|\\bselect\\b|\\bcount\\b|\\bupdatexml\\b|\\bsleep\\b|group\\s+by|\\bunion\\b|\\bdrop\\b|\\btruncate\\b|\\balter\\b|\\bgrant\\b|\\bexecute\\b|\\bxp_cmdshell\\b|\\bcall\\b|\\bdeclare\\b|\\bsql\\b)");
|
||||
/**
|
||||
* sql注入警告语
|
||||
*/
|
||||
private final static String SQL_INJECTION_MESSAGE = "SQL keyword injection prevention processing!";
|
||||
private static final String EQUAL = "_equal";
|
||||
private static final String NOT_EQUAL = "_notequal";
|
||||
private static final String LIKE = "_like";
|
||||
private static final String LIKE_LEFT = "_likeleft";
|
||||
private static final String LIKE_RIGHT = "_likeright";
|
||||
private static final String NOT_LIKE = "_notlike";
|
||||
private static final String GE = "_ge";
|
||||
private static final String LE = "_le";
|
||||
private static final String GT = "_gt";
|
||||
private static final String LT = "_lt";
|
||||
private static final String DATE_GE = "_datege";
|
||||
private static final String DATE_GT = "_dategt";
|
||||
private static final String DATE_EQUAL = "_dateequal";
|
||||
private static final String DATE_LT = "_datelt";
|
||||
private static final String DATE_LE = "_datele";
|
||||
private static final String IS_NULL = "_null";
|
||||
private static final String NOT_NULL = "_notnull";
|
||||
private static final String IGNORE = "_ignore";
|
||||
|
||||
/**
|
||||
* 条件构造器
|
||||
*
|
||||
* @param query 查询字段
|
||||
* @param qw 查询包装类
|
||||
*/
|
||||
public static void buildCondition(Map<String, Object> query, QueryWrapper<?> qw) {
|
||||
if (Func.isEmpty(query)) {
|
||||
return;
|
||||
}
|
||||
query.forEach((k, v) -> {
|
||||
if (Func.hasEmpty(k, v) || k.endsWith(IGNORE)) {
|
||||
return;
|
||||
}
|
||||
// 过滤sql注入关键词
|
||||
k = filter(k);
|
||||
if (k.endsWith(EQUAL)) {
|
||||
qw.eq(getColumn(k, EQUAL), v);
|
||||
} else if (k.endsWith(NOT_EQUAL)) {
|
||||
qw.ne(getColumn(k, NOT_EQUAL), v);
|
||||
} else if (k.endsWith(LIKE_LEFT)) {
|
||||
qw.likeLeft(getColumn(k, LIKE_LEFT), v);
|
||||
} else if (k.endsWith(LIKE_RIGHT)) {
|
||||
qw.likeRight(getColumn(k, LIKE_RIGHT), v);
|
||||
} else if (k.endsWith(NOT_LIKE)) {
|
||||
qw.notLike(getColumn(k, NOT_LIKE), v);
|
||||
} else if (k.endsWith(GE)) {
|
||||
qw.ge(getColumn(k, GE), v);
|
||||
} else if (k.endsWith(LE)) {
|
||||
qw.le(getColumn(k, LE), v);
|
||||
} else if (k.endsWith(GT)) {
|
||||
qw.gt(getColumn(k, GT), v);
|
||||
} else if (k.endsWith(LT)) {
|
||||
qw.lt(getColumn(k, LT), v);
|
||||
} else if (k.endsWith(DATE_GE)) {
|
||||
qw.ge(getColumn(k, DATE_GE), DateUtil.parse(String.valueOf(v), DateUtil.PATTERN_DATETIME));
|
||||
} else if (k.endsWith(DATE_GT)) {
|
||||
qw.gt(getColumn(k, DATE_GT), DateUtil.parse(String.valueOf(v), DateUtil.PATTERN_DATETIME));
|
||||
} else if (k.endsWith(DATE_EQUAL)) {
|
||||
qw.eq(getColumn(k, DATE_EQUAL), DateUtil.parse(String.valueOf(v), DateUtil.PATTERN_DATETIME));
|
||||
} else if (k.endsWith(DATE_LE)) {
|
||||
qw.le(getColumn(k, DATE_LE), DateUtil.parse(String.valueOf(v), DateUtil.PATTERN_DATETIME));
|
||||
} else if (k.endsWith(DATE_LT)) {
|
||||
qw.lt(getColumn(k, DATE_LT), DateUtil.parse(String.valueOf(v), DateUtil.PATTERN_DATETIME));
|
||||
} else if (k.endsWith(IS_NULL)) {
|
||||
qw.isNull(getColumn(k, IS_NULL));
|
||||
} else if (k.endsWith(NOT_NULL)) {
|
||||
qw.isNotNull(getColumn(k, NOT_NULL));
|
||||
} else {
|
||||
qw.like(getColumn(k, LIKE), v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库字段
|
||||
*
|
||||
* @param column 字段名
|
||||
* @param keyword 关键字
|
||||
* @return
|
||||
*/
|
||||
private static String getColumn(String column, String keyword) {
|
||||
return StringUtil.humpToUnderline(StringUtil.removeSuffix(column, keyword));
|
||||
}
|
||||
|
||||
/**
|
||||
* 把SQL关键字替换为空字符串
|
||||
*
|
||||
* @param param 关键字
|
||||
* @return string
|
||||
*/
|
||||
@SneakyThrows(SQLException.class)
|
||||
public static String filter(String param) {
|
||||
if (param == null) {
|
||||
return null;
|
||||
}
|
||||
// 将校验到的sql关键词替换为空字符串
|
||||
String sql = param.replaceAll(SQL_REGEX, StringPool.EMPTY);
|
||||
// 二次校验,避免双写绕过等情况出现
|
||||
if (match(sql)) {
|
||||
throw new SQLException(SQL_INJECTION_MESSAGE);
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符是否包含SQL关键字
|
||||
*
|
||||
* @param param 关键字
|
||||
* @return boolean
|
||||
*/
|
||||
public static Boolean match(String param) {
|
||||
return Func.isNotEmpty(param) && PATTERN.matcher(param).find();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: DreamLu (596392912@qq.com)
|
||||
*/
|
||||
package org.springblade.core.mp.utils;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.springblade.core.tool.utils.BeanUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 分页工具类
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public class PageUtil {
|
||||
|
||||
/**
|
||||
* 2个 IPage 转 Page
|
||||
*
|
||||
* @param page IPage
|
||||
* @param target 需要copy转换的类型
|
||||
* @param <T> 泛型
|
||||
* @return PageResult
|
||||
*/
|
||||
public static <T> Page<T> toPage(IPage<?> page, Class<T> target) {
|
||||
List<T> records = BeanUtil.copy(page.getRecords(), target);
|
||||
return toPage(page, records);
|
||||
}
|
||||
|
||||
/**
|
||||
* 2个 IPage 转 Page
|
||||
*
|
||||
* @param page IPage
|
||||
* @param records 转换过的list模型
|
||||
* @param <T> 泛型
|
||||
* @return PageResult
|
||||
*/
|
||||
public static <T> Page<T> toPage(IPage<?> page, List<T> records) {
|
||||
Page<T> pageResult = new Page<>();
|
||||
pageResult.setCurrent(page.getCurrent());
|
||||
pageResult.setSize(page.getSize());
|
||||
pageResult.setPages(page.getPages());
|
||||
pageResult.setTotal(page.getTotal());
|
||||
pageResult.setRecords(records);
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page 转换
|
||||
*
|
||||
* @param page IPage
|
||||
* @param function 转换过的函数
|
||||
* @param <T> 泛型
|
||||
* @return PageResult
|
||||
*/
|
||||
public static <T, R> Page<R> toPage(IPage<T> page, Function<T, R> function) {
|
||||
List<R> records = new ArrayList<>();
|
||||
for (T record : page.getRecords()) {
|
||||
records.add(function.apply(record));
|
||||
}
|
||||
return toPage(page, records);
|
||||
}
|
||||
|
||||
}
|
||||
35
blade-starter-mybatis/src/main/resources/blade-mybatis.yml
Normal file
35
blade-starter-mybatis/src/main/resources/blade-mybatis.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
#多数据源Sql日志配置
|
||||
spring:
|
||||
datasource:
|
||||
dynamic:
|
||||
druid:
|
||||
proxy-filters:
|
||||
- sqlLogInterceptor
|
||||
|
||||
#mybatis-plus配置
|
||||
mybatis-plus:
|
||||
mapper-locations: classpath:org/springblade/**/mapper/*Mapper.xml
|
||||
#实体扫描,多个package用逗号或者分号分隔
|
||||
typeAliasesPackage: org.springblade.**.entity
|
||||
#typeEnumsPackage: org.springblade.dashboard.entity.enums
|
||||
global-config:
|
||||
# 关闭MP3.0自带的banner
|
||||
banner: false
|
||||
db-config:
|
||||
#主键类型 0:"数据库ID自增", 1:"不操作", 2:"用户输入ID",3:"数字型snowflake", 4:"全局唯一ID UUID", 5:"字符串型snowflake";
|
||||
id-type: assign_id
|
||||
#字段策略
|
||||
insert-strategy: not_null
|
||||
update-strategy: not_null
|
||||
where-strategy: not_null
|
||||
#驼峰下划线转换
|
||||
table-underline: true
|
||||
# 逻辑删除配置
|
||||
# 逻辑删除全局值(1表示已删除,这也是Mybatis Plus的默认配置)
|
||||
logic-delete-value: 1
|
||||
# 逻辑未删除全局值(0表示未删除,这也是Mybatis Plus的默认配置)
|
||||
logic-not-delete-value: 0
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
cache-enabled: false
|
||||
jdbc-type-for-null: 'null'
|
||||
Reference in New Issue
Block a user