微服务版后端初始化

This commit is contained in:
yaoyn
2025-02-08 17:51:37 +08:00
parent 54af6be188
commit da009a7cc4
1897 changed files with 429541 additions and 81 deletions

View File

@ -0,0 +1,153 @@
<?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">
<parent>
<artifactId>xjrsoft-common</artifactId>
<groupId>com.xjrsoft</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>xjrsoft-common-mybatis</artifactId>
<properties>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<dependencies>
<!--引入Lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>${lombok.version}</version>
</dependency>
<!--引入mybatis-plus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- mybatis-plus 多表关联 -->
<dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.xjrsoft</groupId>
<artifactId>xjrsoft-common-core</artifactId>
<version>${xjrsoft.framework.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--引入oracle依赖-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0.1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/ojdbc7.jar</systemPath>
</dependency>
<!-- 引入kingbase依赖 -->
<dependency>
<groupId>kingbase</groupId>
<artifactId>kingbase</artifactId>
<version>8.6.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/kingbase8-8.6.0.jar</systemPath>
</dependency>
<!--引入达梦依赖-->
<dependency>
<groupId>com.dm</groupId>
<artifactId>DmJdbcDriver</artifactId>
<version>8.1.2.192</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/DmJdbcDriver18-8.1.2.192.jar</systemPath>
</dependency>
<dependency>
<groupId>com.xjrsoft</groupId>
<artifactId>xjrsoft-common-satoken</artifactId>
<version>${xjrsoft.framework.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.xjrsoft</groupId>
<artifactId>xjrsoft-common-generate</artifactId>
<version>${xjrsoft.framework.version}</version>
</dependency>
<dependency>
<groupId>com.xjrsoft</groupId>
<artifactId>xjrsoft-common-redis</artifactId>
<version>${xjrsoft.framework.version}</version>
</dependency>
<dependency>
<groupId>com.xjrsoft</groupId>
<artifactId>xjrsoft-common-tenant</artifactId>
<version>${xjrsoft.framework.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
</dependency>
<dependency>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,293 @@
package com.xjrsoft.common.mybatis;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.GlobalDbConfig;
import com.baomidou.dynamic.datasource.provider.AbstractJdbcDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidConfig;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.xjrsoft.common.core.constant.GlobalConstant;
import com.xjrsoft.common.mybatis.handler.MyLocalDateTimeTypeHandler;
import com.xjrsoft.common.mybatis.handler.XjrLocalTimeTypeHandler;
import com.xjrsoft.common.mybatis.interceptor.DataScopeInnerInterceptor;
import com.xjrsoft.common.mybatis.utils.DatasourceUtil;
import com.xjrsoft.tenant.config.TenantConfig;
import com.xjrsoft.tenant.util.SecureUtil;
import com.xjrsoft.tenant.util.TenantUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.apache.ibatis.type.BooleanTypeHandler;
import org.apache.ibatis.type.EnumTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.ssssssss.magicapi.datasource.model.MagicDynamicDataSource;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* @Author: tzx
* @Date: 2023/9/26 15:17
*/
@Slf4j
@Configuration
@RequiredArgsConstructor
public class MybatisplusAutoConfiguration implements WebMvcConfigurer {
private final DynamicDataSourceProperties dynamicDataSourceProperties;
private final Map<String, String> datasourceMap = new HashMap<>();
private final TenantConfig tenantConfig;
/**
* 新多租户插件配置,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存万一出现问题
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
if(!tenantConfig.getEnabled()){
return interceptor;
}
// 如果用了分页插件注意先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
// 用了分页插件必须设置 MybatisConfiguration#useDeprecatedExecutor = false
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
@Override
public Expression getTenantId() {
if (TenantUtil.isNoTenant()) {
return null;
}
try {
return new LongValue(SecureUtil.getTenantId());
}
catch (Exception e) {
log.error("获取当前登录用户租户码失败");
}
return null;
}
// 这是 default 方法,默认返回 false 表示所有表都需要拼多租户条件
@Override
public boolean ignoreTable(String tableName) {
if (TenantUtil.isNoTenant()) {
return true;
}
return tenantConfig.getIgnoreTable().contains(tableName);
}
}));
return interceptor;
}
/**
* 分页插件
*/
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
/**
* 数据权限插件
*/
@Bean
public MybatisPlusInterceptor dataScopeInnerInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new DataScopeInnerInterceptor());
return interceptor;
}
/**
* 防止全表更新与删除
*/
@Bean
public MybatisPlusInterceptor blockAttackInnerInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return interceptor;
}
@Bean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
// 自定义表单hutool包配置查询表单发布的菜单数据设置返回的字段名大小写敏感
GlobalDbConfig.setCaseInsensitive(false);
DataSourceProperty datasource = dynamicDataSourceProperties.getDatasource().get(GlobalConstant.DEFAULT_DATASOURCE_KEY);
return new AbstractJdbcDataSourceProvider(datasource.getDriverClassName(), datasource.getUrl(), datasource.getUsername(), datasource.getPassword()) {
@Override
protected Map<String, DataSourceProperty> executeStmt(Statement statement) throws SQLException {
Map<String, DataSourceProperty> map = new HashMap<>(16);
// 数据库里的所有库
ResultSet rs = statement.executeQuery("SELECT * FROM xjr_databaselink WHERE delete_mark = 0 AND enabled_mark = 1");
while (rs.next()) {
long id = rs.getLong("id");
String host = rs.getString("host");
String username = rs.getString("username");
String password = rs.getString("password");
String driver = rs.getString("driver");
String dbType = rs.getString("db_type");
//缓存起来
datasourceMap.put(Convert.toStr(id), rs.getString("db_name"));
DataSourceProperty property = new DataSourceProperty();
property.setUsername(username);
property.setPassword(password);
property.setUrl(host);
property.setDriverClassName(driver);
// 测试连接,如果连接不上则跳过,避免启动失败
if (!DatasourceUtil.testConnection(host, username, password)) {
continue;
}
DruidConfig druidConfig = property.getDruid();
druidConfig.setInitialSize(10); // 初始化大小
druidConfig.setMaxActive(100);// 最大连接池
druidConfig.setMinIdle(10);// 最小连接池
druidConfig.setMaxWait(60000); //最大等待超时时间
druidConfig.setPoolPreparedStatements(false); // 是否缓存preparedStatement也就是PSCache 官方建议MySQL下建议关闭 个人建议如果想用SQL防火墙 建议打开
druidConfig.setMaxPoolPreparedStatementPerConnectionSize(20);//是否缓存preparedStatement也就是PSCache 官方建议MySQL下建议关闭 个人建议如果想用SQL防火墙 建议打开
druidConfig.setTimeBetweenEvictionRunsMillis(60000L);// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
druidConfig.setMinEvictableIdleTimeMillis(300000L); // 配置一个连接在池中最小生存的时间,单位是毫秒
if (StrUtil.equals(dbType, "oracle")) {
druidConfig.setValidationQuery("SELECT 1 FROM DUAL");
} else {
druidConfig.setValidationQuery("SELECT 1 "); //测试链接 语句
}
druidConfig.setTestWhileIdle(true);
druidConfig.setTestOnReturn(false);
druidConfig.setTestOnBorrow(false);
druidConfig.setFilters("stat,slf4j"); // # 配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
druidConfig.setUseGlobalDataSourceStat(true);
Properties properties = new Properties();
properties.put("druid.stat.mergeSql", true); //打开mergeSql功能
properties.put("druid.stat.slowSqlMillis", true); // 打开慢sql 记录功能
druidConfig.setConnectionProperties(properties);
map.put(Long.toString(id), property);
}
// yml配置的数据源
Map<String, DataSourceProperty> datasourceMap = dynamicDataSourceProperties.getDatasource();
for (DataSourceProperty dataSourceProperty : datasourceMap.values()) {
// 测试连接,如果连接不上则跳过,避免启动失败
if (!DatasourceUtil.testConnection(dataSourceProperty.getUrl(), dataSourceProperty.getUsername(), dataSourceProperty.getPassword())) {
continue;
}
DruidConfig druidConfig = dataSourceProperty.getDruid();
druidConfig.setInitialSize(10); // 初始化大小
druidConfig.setMaxActive(100);// 最大连接池
druidConfig.setMinIdle(10);// 最小连接池
druidConfig.setMaxWait(60000); //最大等待超时时间
druidConfig.setPoolPreparedStatements(false); // 是否缓存preparedStatement也就是PSCache 官方建议MySQL下建议关闭 个人建议如果想用SQL防火墙 建议打开
druidConfig.setMaxPoolPreparedStatementPerConnectionSize(20);//是否缓存preparedStatement也就是PSCache 官方建议MySQL下建议关闭 个人建议如果想用SQL防火墙 建议打开
druidConfig.setTimeBetweenEvictionRunsMillis(60000L);// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
druidConfig.setMinEvictableIdleTimeMillis(300000L); // 配置一个连接在池中最小生存的时间,单位是毫秒
if (dataSourceProperty.getUrl().contains("oracle")) {
druidConfig.setValidationQuery("SELECT 1 FROM DUAL"); //测试链接 如果是oracle 语句不一样
} else {
druidConfig.setValidationQuery("SELECT 1 "); //测试链接 语句
}
druidConfig.setTestWhileIdle(true);
druidConfig.setTestOnReturn(false);
druidConfig.setTestOnBorrow(false);
druidConfig.setFilters("stat,slf4j"); // # 配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
druidConfig.setUseGlobalDataSourceStat(true);
Properties properties = new Properties();
properties.put("druid.stat.mergeSql", true); //打开mergeSql功能
properties.put("druid.stat.slowSqlMillis", true); // 打开慢sql 记录功能
druidConfig.setConnectionProperties(properties);
}
map.putAll(datasourceMap);
rs.close();
return map;
}
};
}
/**
* 配置MagicApi多数据源
*
* @return
*/
@Bean
public MagicDynamicDataSource magicDynamicDataSource() {
MagicDynamicDataSource dynamicDataSource = new MagicDynamicDataSource();
Map<String, DataSource> dataSources = dynamicDataSourceProvider().loadDataSources();
for (String ds : dataSources.keySet()) {
if (StrUtil.equals(GlobalConstant.DEFAULT_DATASOURCE_KEY, ds)) {
dynamicDataSource.setDefault(dataSources.get(ds));
} else {
//缓存起来的name
if (datasourceMap.containsKey(ds)) {
String name = MapUtil.getStr(datasourceMap, ds);
dynamicDataSource.add(name, dataSources.get(ds));
}
//配置在yml上的 可能获取不到name
else {
dynamicDataSource.add("datasource_" + ds, dataSources.get(ds));
}
}
}
return dynamicDataSource;
}
/**
* MybatisPlus数据库类型处理
* @return
*/
@Bean
public ConfigurationCustomizer getConfig(){
return new ConfigurationCustomizer() {
@Override
public void customize(MybatisConfiguration configuration) {
configuration.setMapUnderscoreToCamelCase(true);
configuration.setJdbcTypeForNull(JdbcType.NULL);
configuration.getTypeAliasRegistry().registerAlias("EnumTypeHandler", EnumTypeHandler.class);
configuration.getTypeAliasRegistry().registerAlias("BooleanTypeHandler", BooleanTypeHandler.class);
configuration.getTypeAliasRegistry().registerAlias("AbstractJsonTypeHandler", AbstractJsonTypeHandler.class);
configuration.getTypeHandlerRegistry().register(LocalDateTime.class, MyLocalDateTimeTypeHandler.class);
configuration.getTypeHandlerRegistry().register(LocalTime.class, XjrLocalTimeTypeHandler.class);
}
};
}
}

View File

@ -0,0 +1,193 @@
package com.xjrsoft.common.mybatis.config;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.converters.ConverterKeyBuild;
import com.alibaba.excel.converters.DefaultConverterLoader;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.xjrsoft.common.mybatis.handler.EasyExcelLocalDateTimeConverter;
import com.xjrsoft.common.mybatis.handler.EasyExcelLocalTimeConverter;
import com.xjrsoft.common.mybatis.utils.LocalDateTimeUtil;
import lombok.SneakyThrows;
import oracle.sql.INTERVALDS;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
/**
* @Author: tzx
* @Date: 2022/8/2 16:54
*/
@Configuration
public class JacksonConfig {
@Value("${spring.jackson.date-format}")
private String pattern;
/**
* 默认设置所有long类型 序列化返回前端 全变成string
* 所有LocalDatetime 序列号返回前端 全部格式化
* @return
*/
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> {
builder.serializerByType(Long.class, ToStringSerializer.instance);
builder.serializerByType(Long.TYPE, ToStringSerializer.instance);
builder.serializerByType(BigDecimal.class, bigDecimalSerializer());
builder.serializerByType(LocalDateTime.class, localDateTimeSerializer());
builder.serializerByType(INTERVALDS.class, intervalDSSerializer());
builder.featuresToEnable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
builder.deserializerByType(LocalDateTime.class, localDateTimeDeserializer());
builder.visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
builder.visibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
builder.visibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE);
builder.visibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NONE);
};
}
/**
* Jackson格式化BigDecimal类型数据
* @return
*/
public ToStringSerializerBase bigDecimalSerializer() {
return new ToStringSerializerBase(BigDecimal.class) {
protected final static int MAX_BIG_DECIMAL_SCALE = 9999;
@Override
public String valueToString(Object value) {
throw new IllegalStateException();
}
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
if (gen.isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN)) {
final BigDecimal bd = (BigDecimal) value;
// 24-Aug-2016, tatu: [core#315] prevent possible DoS vector, so we need this
if (!_verifyBigDecimalRange(gen, bd)) {
// ... but wouldn't it be nice to trigger error via generator? Alas,
// no method to do that. So we'll do...
final String errorMsg = String.format(
"Attempt to write plain `java.math.BigDecimal` (see JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN) with illegal scale (%d): needs to be between [-%d, %d]",
bd.scale(), MAX_BIG_DECIMAL_SCALE, MAX_BIG_DECIMAL_SCALE);
provider.reportMappingProblem(errorMsg);
}
// text = bd.toPlainString();
gen.writeNumber(bd);
} else {
gen.writeString(value.toString());
}
}
// 24-Aug-2016, tatu: [core#315] prevent possible DoS vector, so we need this
protected boolean _verifyBigDecimalRange(JsonGenerator gen, BigDecimal value) throws IOException {
int scale = value.scale();
return ((scale >= -MAX_BIG_DECIMAL_SCALE) && (scale <= MAX_BIG_DECIMAL_SCALE));
}
};
}
/**
* localDatetime格式化
* @return
*/
@Bean
public LocalDateTimeSerializer localDateTimeSerializer(){
return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
}
/**
* oracle字段类型INTERVALDS格式化
* @return
*/
@Bean
public JsonSerializer<INTERVALDS> intervalDSSerializer() {
return new JsonSerializer<INTERVALDS>() {
@Override
public void serialize(INTERVALDS time, JsonGenerator g, SerializerProvider provider) throws IOException {
g.writeString(LocalDateTimeUtil.convertIntervalToLocalTime(time).format(DateTimeFormatter.ISO_LOCAL_TIME));
}
};
}
/**
* localDatetime格式化
* @return
*/
@Bean
public JsonDeserializer<LocalDateTime> localDateTimeDeserializer(){
final String pattern = this.pattern;
return new JsonDeserializer<LocalDateTime>(){
@SneakyThrows
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext context) throws IOException {
String value = p.getText();
if (StrUtil.isEmpty(value)) {
return null;
}
Class<?> aClass = p.getCurrentValue().getClass();
Field field = ReflectUtil.getField(aClass, p.getCurrentName());
String format = pattern;
JsonFormat annotation = field.getAnnotation(JsonFormat.class);
if (annotation != null) {
format = StringUtils.defaultIfEmpty(annotation.pattern(), pattern);
}
return LocalDateTimeUtil.parseDate(value, format);
}
};
}
@Bean
public Converter<String, LocalDateTime> stringToLocalDateTimeConverter() {
/** EasyExcel时间格式配置 */
EasyExcelLocalDateTimeConverter dateTimeConverter = new EasyExcelLocalDateTimeConverter();
DefaultConverterLoader.loadDefaultReadConverter().put(ConverterKeyBuild.buildKey(dateTimeConverter.supportJavaTypeKey(), dateTimeConverter.supportExcelTypeKey()), dateTimeConverter);
DefaultConverterLoader.loadDefaultWriteConverter().put(ConverterKeyBuild.buildKey(dateTimeConverter.supportJavaTypeKey(), dateTimeConverter.supportExcelTypeKey()), dateTimeConverter);
DefaultConverterLoader.loadDefaultWriteConverter().put(ConverterKeyBuild.buildKey(dateTimeConverter.supportJavaTypeKey()), dateTimeConverter);
EasyExcelLocalTimeConverter timeConverter = new EasyExcelLocalTimeConverter();
DefaultConverterLoader.loadDefaultReadConverter().put(ConverterKeyBuild.buildKey(timeConverter.supportJavaTypeKey(), timeConverter.supportExcelTypeKey()), timeConverter);
DefaultConverterLoader.loadDefaultWriteConverter().put(ConverterKeyBuild.buildKey(timeConverter.supportJavaTypeKey(), timeConverter.supportExcelTypeKey()), timeConverter);
DefaultConverterLoader.loadDefaultWriteConverter().put(ConverterKeyBuild.buildKey(timeConverter.supportJavaTypeKey()), timeConverter);
/***/
return new Converter<String, LocalDateTime>() {
@Override
public LocalDateTime convert(String value) {
return LocalDateTimeUtil.parseDateByLength(value);
}
};
}
@Bean
public Converter<String, LocalTime> stringToLocalTimeConverter() {
return new Converter<String, LocalTime>(){
@Override
public LocalTime convert(String value) {
if (StrUtil.isNotBlank(value)) {
return LocalTime.parse(value);
}
return null;
}
};
}
}

View File

@ -0,0 +1,32 @@
package com.xjrsoft.common.mybatis.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.springframework.stereotype.Component;
import java.sql.*;
@Component
@MappedTypes(Clob.class)
public class ClobTypeHandler extends BaseTypeHandler<Clob> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Clob parameter, JdbcType jdbcType) throws SQLException {
ps.setCharacterStream(i, parameter.getCharacterStream());
}
@Override
public Clob getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getClob(columnName);
}
@Override
public Clob getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return rs.getClob(columnIndex);
}
@Override
public Clob getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return cs.getClob(columnIndex);
}
}

View File

@ -0,0 +1,48 @@
package com.xjrsoft.common.mybatis.handler;
import cn.hutool.core.date.DatePattern;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xjrsoft.common.mybatis.utils.LocalDateTimeUtil;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
public class EasyExcelLocalDateTimeConverter implements Converter<LocalDateTime> {
@Override
public Class<LocalDateTime> supportJavaTypeKey() {
return LocalDateTime.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public LocalDateTime convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
return LocalDateTimeUtil.parseDate(cellData.getStringValue(), getFormat(contentProperty));
}
@Override
public WriteCellData<LocalDateTime> convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
return new WriteCellData<>(value.format(DateTimeFormatter.ofPattern(getFormat(contentProperty))));
}
private String getFormat(ExcelContentProperty contentProperty) {
JsonFormat annotation = contentProperty.getField().getAnnotation(JsonFormat.class);
String format = DatePattern.NORM_DATETIME_PATTERN;
if (annotation != null) {
format = annotation.pattern();
}
return format;
}
}

View File

@ -0,0 +1,37 @@
package com.xjrsoft.common.mybatis.handler;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.xjrsoft.common.mybatis.utils.LocalDateTimeUtil;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.LocalTime;
@Component
public class EasyExcelLocalTimeConverter implements Converter<LocalTime> {
@Override
public Class<LocalTime> supportJavaTypeKey() {
return LocalTime.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public LocalTime convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
return LocalDateTimeUtil.parseTime(cellData.getStringValue());
}
@Override
public WriteCellData<LocalDateTime> convertToExcelData(LocalTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
return new WriteCellData<>(LocalDateTimeUtil.format(value));
}
}

View File

@ -0,0 +1,32 @@
package com.xjrsoft.common.mybatis.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.springframework.stereotype.Component;
import java.sql.*;
@MappedTypes(Blob.class)
@Component
public class MyBlobTypeHandler extends BaseTypeHandler<Blob> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Blob parameter, JdbcType jdbcType) throws SQLException {
ps.setBinaryStream(i, parameter.getBinaryStream());
}
@Override
public Blob getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getBlob(columnName);
}
@Override
public Blob getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return rs.getBlob(columnIndex);
}
@Override
public Blob getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return cs.getBlob(columnIndex);
}
}

View File

@ -0,0 +1,39 @@
package com.xjrsoft.common.mybatis.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.springframework.stereotype.Component;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@MappedJdbcTypes(value = {JdbcType.CLOB, JdbcType.NCLOB})
@Component
public class MyClobTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
throws SQLException {
ps.setNString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return rs.getNString(columnName);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return rs.getNString(columnIndex);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getNString(columnIndex);
}
}

View File

@ -0,0 +1,49 @@
package com.xjrsoft.common.mybatis.handler;
import oracle.sql.TIMESTAMP;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.LocalDateTimeTypeHandler;
import java.sql.*;
import java.time.LocalDateTime;
/**
* @author Zexy
*/
public class MyLocalDateTimeTypeHandler extends LocalDateTimeTypeHandler {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType)
throws SQLException {
ps.setObject(i, Timestamp.valueOf(parameter));
}
@Override
public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
Object object = rs.getObject(columnName);
return getLocalDateTime(object);
}
@Override
public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
Object object = rs.getObject(columnIndex);
return getLocalDateTime(object);
}
@Override
public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
Object object = cs.getObject(columnIndex);
return getLocalDateTime(object);
}
private static LocalDateTime getLocalDateTime(Object object) throws SQLException {
if (object instanceof LocalDateTime) {
return (LocalDateTime) object;
} else if(object instanceof Timestamp){//在这里强行转换将sql的时间转换为LocalDateTime
return ((Timestamp)object).toLocalDateTime();
} else if (object instanceof TIMESTAMP) {
return ((TIMESTAMP) object).timestampValue().toLocalDateTime();
}
return null;
}
}

View File

@ -0,0 +1,77 @@
package com.xjrsoft.common.mybatis.handler;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.xjrsoft.common.core.constant.GlobalConstant;
import com.xjrsoft.common.core.enums.DeleteMark;
import com.xjrsoft.common.core.enums.EnabledMark;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @title 数据审计处理器
* @desc 用于新增或者更新 自动插入 相应字段
* @author tzx
* @create 2020年11月9日 11:30:59
* */
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* @title 新增自动填充
* @desc fieldName 使用实体类字段名 而不是数据库字段名
* */
@Override
public void insertFill(MetaObject metaObject) {
long userId = 0L;
try {
userId = StpUtil.getLoginIdAsLong();
}
catch (Exception e) {
log.error("获取当前登录用户Id失败", e);
}
//如果需要自定义主键生成策略 在此按照自己想法生成主键值
//this.strictInsertFill(metaObject, {主键字段名}, {主键字段类型.class}, {自己生成的主键id值});
//例如: this.strictInsertFill(metaObject, "id", Integer.class, 10000000000000);
//默认插入创建人Id
this.strictInsertFill(metaObject, GlobalConstant.CREATE_USER_ID_PROPERTY, Long.class, userId);
//默认插入创建时间
this.strictInsertFill(metaObject, GlobalConstant.CREATE_DATE_PROPERTY, LocalDateTime.class, LocalDateTime.now());
//默认插入未删除
this.strictInsertFill(metaObject, GlobalConstant.DELETE_MARK_PROPERTY, Integer.class, DeleteMark.NODELETE.getCode());
//默认插入已启用
this.strictInsertFill(metaObject, GlobalConstant.ENABLED_MARK_PROPERTY, Integer.class, EnabledMark.ENABLED.getCode());
//权限所属人id
this.strictInsertFill(metaObject, GlobalConstant.AUTH_USER_ID_PROPERTY, Long.class, userId);
}
/**
* @title 修改自动填充
* @desc fieldName 使用实体类字段名 而不是数据库字段名
* */
@Override
public void updateFill(MetaObject metaObject) {
long userId = 0L;
try {
userId = StpUtil.getLoginIdAsLong();
}
catch (Exception e) {
log.error("获取当前登录用户Id失败", e);
}
//默认插入修改人Id
this.strictUpdateFill(metaObject, GlobalConstant.MODIFY_USER_ID_PROPERTY, Long.class, userId);
//默认插入修改时间
this.strictUpdateFill(metaObject, GlobalConstant.MODIFY_DATE_PROPERTY, LocalDateTime.class, LocalDateTime.now());
}
}

View File

@ -0,0 +1,39 @@
package com.xjrsoft.common.mybatis.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.springframework.stereotype.Component;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@MappedJdbcTypes(value = JdbcType.NVARCHAR)
@Component
public class MyNVarCharTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
throws SQLException {
ps.setNString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return rs.getString(columnName);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return rs.getNString(columnIndex);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return cs.getNString(columnIndex);
}
}

View File

@ -0,0 +1,45 @@
package com.xjrsoft.common.mybatis.handler;
import cn.hutool.db.Entity;
import cn.hutool.db.handler.RsHandler;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
public class XjrEntityHandler implements RsHandler<Entity> {
/** 是否大小写不敏感 */
private final boolean caseInsensitive;
/**
* 创建一个 EntityHandler对象
* @return EntityHandler对象
*/
public static XjrEntityHandler create() {
return new XjrEntityHandler();
}
/**
* 构造
*/
public XjrEntityHandler() {
this(false);
}
/**
* 构造
*
* @param caseInsensitive 是否大小写不敏感
*/
public XjrEntityHandler(boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
}
@Override
public Entity handle(ResultSet rs) throws SQLException {
final ResultSetMetaData meta = rs.getMetaData();
final int columnCount = meta.getColumnCount();
return rs.next() ? XjrHandleHelper.handleRow(columnCount, meta, rs, this.caseInsensitive) : null;
}
}

View File

@ -0,0 +1,44 @@
package com.xjrsoft.common.mybatis.handler;
import cn.hutool.db.Entity;
import cn.hutool.db.handler.RsHandler;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class XjrEntityListHandler implements RsHandler<List<Entity>> {
/** 是否大小写不敏感 */
private final boolean caseInsensitive;
/**
* 创建一个 EntityListHandler对象
* @return EntityListHandler对象
*/
public static XjrEntityListHandler create() {
return new XjrEntityListHandler();
}
/**
* 构造
*/
public XjrEntityListHandler() {
this(false);
}
/**
* 构造
*
* @param caseInsensitive 是否大小写不敏感
*/
public XjrEntityListHandler(boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
}
@Override
public List<Entity> handle(ResultSet rs) throws SQLException {
return XjrHandleHelper.handleRs(rs, new ArrayList<>(), this.caseInsensitive);
}
}

View File

@ -0,0 +1,310 @@
package com.xjrsoft.common.mybatis.handler;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.PropDesc;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.TypeUtil;
import cn.hutool.db.Entity;
import cn.hutool.db.handler.HandleHelper;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class XjrHandleHelper extends HandleHelper {
/**
* 处理单条数据
*
* @param <T> Bean类型
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param bean 目标Bean
* @return 每一行的Entity
* @throws SQLException SQL执行异常
* @since 3.3.1
*/
public static <T> T handleRow(int columnCount, ResultSetMetaData meta, ResultSet rs, T bean) throws SQLException {
return handleRow(columnCount, meta, rs).toBeanIgnoreCase(bean);
}
/**
* 处理单条数据
*
* @param <T> Bean类型
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param beanClass 目标Bean类型
* @return 每一行的Entity
* @throws SQLException SQL执行异常
* @since 3.3.1
*/
@SuppressWarnings("unchecked")
public static <T> T handleRow(int columnCount, ResultSetMetaData meta, ResultSet rs, Class<T> beanClass) throws SQLException {
Assert.notNull(beanClass, "Bean Class must be not null !");
if(beanClass.isArray()) {
//返回数组
final Class<?> componentType = beanClass.getComponentType();
final Object[] result = ArrayUtil.newArray(componentType, columnCount);
for(int i = 0,j = 1; i < columnCount; i++, j++) {
result[i] = getColumnValue(rs, j, meta.getColumnType(j), componentType);
}
return (T) result;
} else if(Iterable.class.isAssignableFrom(beanClass)) {
//集合
final Object[] objRow = handleRow(columnCount, meta, rs, Object[].class);
return Convert.convert(beanClass, objRow);
} else if(beanClass.isAssignableFrom(Entity.class)) {
//Entity的父类都可按照Entity返回
return (T) handleRow(columnCount, meta, rs);
} else if(String.class == beanClass) {
//字符串
final Object[] objRow = handleRow(columnCount, meta, rs, Object[].class);
return (T) StrUtil.join(", ", objRow);
}
//普通bean
final T bean = ReflectUtil.newInstanceIfPossible(beanClass);
//忽略字段大小写
final Map<String, PropDesc> propMap = BeanUtil.getBeanDesc(beanClass).getPropMap(true);
String columnLabel;
PropDesc pd;
Method setter;
Object value;
for (int i = 1; i <= columnCount; i++) {
columnLabel = meta.getColumnLabel(i);
pd = propMap.get(columnLabel);
if(null == pd) {
// 尝试驼峰命名风格
pd = propMap.get(StrUtil.toCamelCase(columnLabel));
}
setter = (null == pd) ? null : pd.getSetter();
if(null != setter) {
value = getColumnValue(rs, i, meta.getColumnType(i), TypeUtil.getFirstParamType(setter));
ReflectUtil.invokeWithCheck(bean, setter, value);
}
}
return bean;
}
/**
* 处理单条数据
*
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @return 每一行的Entity
* @throws SQLException SQL执行异常
*/
public static Entity handleRow(int columnCount, ResultSetMetaData meta, ResultSet rs) throws SQLException {
return handleRow(columnCount, meta, rs, false);
}
/**
* 处理单条数据
*
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param caseInsensitive 是否大小写不敏感
* @return 每一行的Entity
* @throws SQLException SQL执行异常
* @since 4.5.16
*/
public static Entity handleRow(int columnCount, ResultSetMetaData meta, ResultSet rs, boolean caseInsensitive) throws SQLException {
return handleRow(new Entity(null, caseInsensitive), columnCount, meta, rs, true);
}
/**
* 处理单条数据
*
* @param <T> Entity及其子对象
* @param row Entity对象
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param withMetaInfo 是否包含表名、字段名等元信息
* @return 每一行的Entity
* @throws SQLException SQL执行异常
* @since 3.3.1
*/
public static <T extends Entity> T handleRow(T row, int columnCount, ResultSetMetaData meta, ResultSet rs, boolean withMetaInfo) throws SQLException {
int type;
for (int i = 1; i <= columnCount; i++) {
type = meta.getColumnType(i);
row.put(meta.getColumnLabel(i), getColumnValue(rs, i, type, null));
}
if (withMetaInfo) {
try {
row.setTableName(meta.getTableName(1));
} catch (SQLException ignore){
//issue#I2AGLU@Gitee
// Hive等NoSQL中无表的概念此处报错跳过。
}
row.setFieldNames(row.keySet());
}
return row;
}
/**
* 处理单条数据
*
* @param rs 数据集
* @return 每一行的Entity
* @throws SQLException SQL执行异常
*/
public static Entity handleRow(ResultSet rs) throws SQLException {
final ResultSetMetaData meta = rs.getMetaData();
final int columnCount = meta.getColumnCount();
return handleRow(columnCount, meta, rs);
}
/**
* 处理单行数据
*
* @param rs 数据集(行)
* @return 每一行的List
* @throws SQLException SQL执行异常
* @since 5.1.6
*/
public static List<Object> handleRowToList(ResultSet rs) throws SQLException {
final ResultSetMetaData meta = rs.getMetaData();
final int columnCount = meta.getColumnCount();
final List<Object> row = new ArrayList<>(columnCount);
for (int i = 1; i <= columnCount; i++) {
row.add(getColumnValue(rs, i, meta.getColumnType(i), null));
}
return row;
}
/**
* 处理多条数据
*
* @param <T> 集合类型
* @param rs 数据集
* @param collection 数据集
* @return Entity列表
* @throws SQLException SQL执行异常
*/
public static <T extends Collection<Entity>> T handleRs(ResultSet rs, T collection) throws SQLException {
return handleRs(rs, collection, false);
}
/**
* 处理多条数据
*
* @param <T> 集合类型
* @param rs 数据集
* @param collection 数据集
* @param caseInsensitive 是否大小写不敏感
* @return Entity列表
* @throws SQLException SQL执行异常
* @since 4.5.16
*/
public static <T extends Collection<Entity>> T handleRs(ResultSet rs, T collection, boolean caseInsensitive) throws SQLException {
final ResultSetMetaData meta = rs.getMetaData();
final int columnCount = meta.getColumnCount();
while (rs.next()) {
collection.add(handleRow(columnCount, meta, rs, caseInsensitive));
}
return collection;
}
/**
* 处理多条数据并返回一个Bean列表
*
* @param <E> 集合元素类型
* @param <T> 集合类型
* @param rs 数据集
* @param collection 数据集
* @param elementBeanType Bean类型
* @return Entity列表
* @throws SQLException SQL执行异常
* @since 3.1.0
*/
public static <E, T extends Collection<E>> T handleRsToBeanList(ResultSet rs, T collection, Class<E> elementBeanType) throws SQLException {
final ResultSetMetaData meta = rs.getMetaData();
final int columnCount = meta.getColumnCount();
while (rs.next()) {
collection.add(handleRow(columnCount, meta, rs, elementBeanType));
}
return collection;
}
// -------------------------------------------------------------------------------------------------------------- Private method start
/**
* 获取字段值<br>
* 针对日期时间等做单独处理判断
*
* @param <T> 返回类型
* @param rs {@link ResultSet}
* @param columnIndex 字段索引
* @param type 字段类型默认Object
* @param targetColumnType 结果要求的类型需进行二次转换null或者Object不转换
* @return 字段值
* @throws SQLException SQL异常
*/
private static <T> Object getColumnValue(ResultSet rs, int columnIndex, int type, Type targetColumnType) throws SQLException {
Object rawValue = null;
switch (type) {
case Types.TIMESTAMP:
try{
rawValue = rs.getTimestamp(columnIndex);
} catch (SQLException ignore){
// issue#776@Github
// 当数据库中日期为0000-00-00 00:00:00报错转为null
}
break;
case Types.TIME:
rawValue = rs.getTime(columnIndex);
break;
case Types.NCLOB:
rawValue = rs.getNString(columnIndex);
break;
case Types.NUMERIC:
ResultSetMetaData metaData = rs.getMetaData();
if (metaData.getScale(columnIndex) == 0) {
// 没有小数点
if (metaData.getPrecision(columnIndex) > 11) {
// 长度大于11转换成Long类型
rawValue = rs.getLong(columnIndex);
} else {
// 长度小于等于11转成Integer类型
rawValue = rs.getInt(columnIndex);
}
} else {
// 有小数点
rawValue = rs.getObject(columnIndex);
}
break;
default:
rawValue = rs.getObject(columnIndex);
}
if (null == targetColumnType || Object.class == targetColumnType) {
// 无需转换
return rawValue;
} else {
// 按照返回值要求转换
return Convert.convert(targetColumnType, rawValue);
}
}
// -------------------------------------------------------------------------------------------------------------- Private method end
}

View File

@ -0,0 +1,75 @@
package com.xjrsoft.common.mybatis.handler;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
import com.xjrsoft.common.mybatis.utils.LocalDateTimeUtil;
import oracle.sql.INTERVALDS;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalTime;
public class XjrLocalTimeTypeHandler extends BaseTypeHandler<LocalTime> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, LocalTime localTime, JdbcType jdbcType)
throws SQLException {
DbType dbType = JdbcUtils.getDbType(ps.getConnection().getMetaData().getURL());
if (dbType == DbType.ORACLE || dbType == DbType.ORACLE_12C) {
// oracle时间类型处理
ps.setObject(i, new INTERVALDS(StringPool.ZERO + StringPool.SPACE + LocalDateTimeUtil.format(localTime) + StringPool.DOT + StringPool.ZERO));
} else {
ps.setObject(i, localTime);
}
}
@Override
public LocalTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
Object object = rs.getObject(columnName);
if (object == null) {
return null;
}
if (object instanceof INTERVALDS) {
return convertIntervalToLocalTime((INTERVALDS) object);
}
return rs.getObject(columnName, LocalTime.class);
}
@Override
public LocalTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
Object object = rs.getObject(columnIndex);
if (object == null) {
return null;
}
if (object instanceof INTERVALDS) {
return convertIntervalToLocalTime((INTERVALDS) object);
}
return rs.getObject(columnIndex, LocalTime.class);
}
@Override
public LocalTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
Object object = cs.getObject(columnIndex);
if (object == null) {
return null;
}
if (object instanceof INTERVALDS) {
return convertIntervalToLocalTime((INTERVALDS) object);
}
return cs.getObject(columnIndex, LocalTime.class);
}
public LocalTime convertIntervalToLocalTime(INTERVALDS intervalDS) {
if (intervalDS == null) {
return null;
}
String str = intervalDS.stringValue();
String timeStr = str.substring(str.indexOf(StringPool.SPACE) + 1, str.indexOf(StringPool.DOT));
String[] array = timeStr.split(StringPool.COLON);
return LocalTime.of(Integer.parseInt(array[0]), Integer.parseInt(array[1]), Integer.parseInt(array[2]));
}
}

View File

@ -0,0 +1,55 @@
package com.xjrsoft.common.mybatis.handler;
import cn.hutool.db.Entity;
import cn.hutool.db.PageResult;
import cn.hutool.db.handler.RsHandler;
import java.sql.ResultSet;
import java.sql.SQLException;
public class XjrPageResultHandler implements RsHandler<PageResult<Entity>> {
private final PageResult<Entity> pageResult;
/**
* 是否大小写不敏感
*/
private final boolean caseInsensitive;
/**
* 创建一个 EntityHandler对象<br>
* 结果集根据给定的分页对象查询数据库,填充结果
*
* @param pageResult 分页结果集空对象
* @return EntityHandler对象
*/
public static XjrPageResultHandler create(PageResult<Entity> pageResult) {
return new XjrPageResultHandler(pageResult);
}
/**
* 构造<br>
* 结果集根据给定的分页对象查询数据库,填充结果
*
* @param pageResult 分页结果集空对象
*/
public XjrPageResultHandler(PageResult<Entity> pageResult) {
this(pageResult, false);
}
/**
* 构造<br>
* 结果集根据给定的分页对象查询数据库,填充结果
*
* @param pageResult 分页结果集空对象
* @param caseInsensitive 是否大小写不敏感
*/
public XjrPageResultHandler(PageResult<Entity> pageResult, boolean caseInsensitive) {
this.pageResult = pageResult;
this.caseInsensitive = caseInsensitive;
}
@Override
public PageResult<Entity> handle(ResultSet rs) throws SQLException {
return XjrHandleHelper.handleRs(rs, pageResult, this.caseInsensitive);
}
}

View File

@ -0,0 +1,106 @@
package com.xjrsoft.common.mybatis.interceptor;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.xjrsoft.common.mybatis.utils.AuthorityUtil;
import com.xjrsoft.common.redis.service.RedisUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.*;
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 java.util.List;
/**
* 数据权限处理器
*
* @author tzx
* @Date: 2023/2/21 16:11
* @since 3.4.1 +
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class DataScopeInnerInterceptor extends JsqlParserSupport implements InnerInterceptor {
// private DataPermissionHandler dataPermissionHandler;
@Setter
private static RedisUtil redisUtil;
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
return;
}
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
mpBs.sql(parserSingle(mpBs.sql(), ms.getId()));
}
@Override
protected void processSelect(Select select, int index, String sql, Object obj) {
SelectBody selectBody = select.getSelectBody();
if (selectBody instanceof PlainSelect) {
this.setWhere((PlainSelect) selectBody, (String) obj);
} else if (selectBody instanceof SetOperationList) {
SetOperationList setOperationList = (SetOperationList) selectBody;
List<SelectBody> selectBodyList = setOperationList.getSelects();
selectBodyList.forEach(s -> this.setWhere((PlainSelect) s, (String) obj));
}
}
/**
* 设置 where 条件
*
* @param plainSelect 查询对象
* @param whereSegment 查询条件片段
*/
protected void setWhere(PlainSelect plainSelect, String whereSegment) {
//有可能是没有登录的非web请求定时任务初始运行 所以必须要try catch一下
//有可能是没有登录的非web请求定时任务初始运行 所以必须要try catch一下
try {
//首先必须要登录 才需要判断数据权限的问题
if (!StpUtil.isLogin()) {
return;
}
} catch (Exception ignored) {
return;
}
FromItem fromItem = plainSelect.getFromItem();
Table fromTable = (Table) fromItem;
String alias = null;
if (ObjectUtil.isNotNull(fromTable.getAlias())) {
alias = fromTable.getAlias().getName();
}
Expression dataAuthExpression = AuthorityUtil.getDataAuthExpressionByTableName(fromTable.getName(), alias);
Expression currentExpression = plainSelect.getWhere();
if (ObjectUtil.isNotNull(dataAuthExpression)) {
if(currentExpression == null){
currentExpression = dataAuthExpression;
}
else {
currentExpression = new AndExpression(currentExpression, dataAuthExpression);
}
plainSelect.setWhere(currentExpression);
}
}
}

View File

@ -0,0 +1,70 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.github.yulichang.annotation.EntityMapping;
import com.xjrsoft.common.core.domain.base.AuditEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.List;
/**
* <p>
* 数据权限表
* </p>
*
* @author tzx
* @since 2023-02-27
*/
@EqualsAndHashCode(callSuper = true)
@TableName("xjr_data_auth")
@Tag(name = "DataAuth对象", description = "数据权限表")
@Data
public class DataAuth extends AuditEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(name="主键")
private Long id;
@Schema(name = "名称")
private String name;
@Schema(name = "编码")
private String code;
@Schema(name = "类型 0 角色 1 用户")
private Integer authType;
@Schema(name = "授权方式 0 简易 1 自定义")
private Integer authMethod;
@Schema(name = "实现范围 如果是简易模式 就会有这个数据 ")
private Integer authScope;
@Schema(name = "授权公式 如果是自定义模式 就会有这个数据")
private String authFormula;
@Schema(name = "备注")
private String remark;
@Schema(name = "租户id")
private Long tenantId;
@Schema(name = "授权对象")
@TableField(exist = false)
@EntityMapping(thisField = "id", joinField = "dataAuthId")
private List<DataAuthRelation> authObjectList;
@Schema(name = "授权配置 授权方式为1 就会有")
@TableField(exist = false)
@EntityMapping(thisField = "id", joinField = "dataAuthId")
private List<DataAuthConfig> authConfigList;
}

View File

@ -0,0 +1,50 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.OrderBy;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 数据权限自定义配置详情表
* </p>
*
* @author tzx
* @since 2023-02-27
*/
@TableName("xjr_data_auth_config")
@Tag(name = "DataAuthConfig对象", description = "数据权限自定义配置详情表")
@Data
public class DataAuthConfig implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(name ="主键")
private Long id;
@Schema(name ="数据权限表id")
private Long dataAuthId;
@Schema(name ="排序号")
@OrderBy(asc = true)
private Integer orderNumber;
@Schema(name ="字段名")
private String fieldName;
@Schema(name ="条件")
private Integer conditionType;
@Schema(name ="字段类型")
private Integer fieldType;
@Schema(name ="根据字段类型区分 如果是 登陆人信息 默认不需要存储值")
private String fieldValue;
@Schema(name = "租户id")
private Long tenantId;
}

View File

@ -0,0 +1,36 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 数据权限 对象类型关联表
* </p>
*
* @author tzx
* @since 2023-02-27
*/
@TableName("xjr_data_auth_relation")
@Tag(name = "DataAuthRelation对象", description = "数据权限 对象类型关联表")
@Data
public class DataAuthRelation implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(name = "主键")
private Long id;
@Schema(name ="data_auth 表id")
private Long dataAuthId;
@Schema(name ="对象id 如果data_auth 表中的类型是 角色 就是角色id 如果是用户 就是用户id")
private Long objectId;
@Schema(name = "租户id")
private Long tenantId;
}

View File

@ -0,0 +1,36 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 数据权限 与 表 关联关系表
* </p>
*
* @author tzx
* @since 2023-02-28
*/
@TableName("xjr_data_auth_table_relation")
@Tag(name = "DataAuthTableRelation对象", description = "数据权限 与 表 关联关系表")
@Data
public class DataAuthTableRelation implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Schema(name ="表名")
private String tableName;
@Schema(name ="数据权限id")
private Long dataAuthId;
@Schema(name ="租户id")
private Long tenantId;
}

View File

@ -0,0 +1,147 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.TableName;
import com.xjrsoft.common.core.domain.base.AuditEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 机构
* </p>
*
* @author tzx
* @since 2022-03-02
*/
@TableName("xjr_department")
@Tag(name = "Department对象", description = "机构")
@Data
@EqualsAndHashCode(callSuper = false)
public class Department extends AuditEntity implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Schema(name ="机构名称")
private String name;
@Schema(name ="机构名称")
private Long parentId;
@Schema(name ="编码")
private String code;
public Department(){
}
public Department(Long id,String code,String name,Long parentId){
this.id=id;
this.code=code;
this.name=name;
this.parentId=parentId;
setIsSync("Y");
}
@Schema(name ="电话")
private String mobile;
@Schema(name ="邮箱")
private String email;
@Schema(name ="主页")
private String website;
@Schema(name ="地址")
private String address;
@Schema(name ="排序号")
private Integer sortCode;
@Schema(name ="备注")
private String remark;
@Schema(name ="层级")
private String hierarchy;
@Schema(name ="组织类别3总部2板块1公司0部门")
private Integer departmentType;
@Schema(name ="租户id")
private Long tenantId;
@Schema(name ="是否同步")
private String isSync;
@Schema(name ="对应企业微信部门id")
private Long wechatDeptId;
@Schema(name ="对应钉钉部门id")
private Long dingtalkDeptId;
private String dingAgentId;
private String dingAppKey;
private String dingAppSecret;
@Schema(name ="简称")
private String shortName;
@Schema(name ="组织性质-数据字典id")
private Long departmentNature;
@Schema(name ="成立时间")
private LocalDateTime establishedTime;
@Schema(name ="管理人-用户id")
private Long custodian;
@Schema(name ="传真")
private String facsimile;
@Schema(name ="行政正职领导-用户id")
private Long administrativeLeader;
@Schema(name ="党委正职领导-用户id")
private Long partyCommitteeLeader;
@Schema(name ="部门领导-ids")
private String departmentLeaders;
@Schema(name ="上级分管领导-ids")
private String chargeOfLeaders;
@Schema(name ="部门标签-数据字典id")
private String departmentLabel;
@Schema(name ="分机号")
private String extensionNumber;
@Schema(name ="所属行业 - 数据字典id")
private Long industry;
@Schema(name ="公司法人")
private String corporateLegalPerson;
@Schema(name ="联系手机")
private String phoneNumber;
@Schema(name ="联系电话")
private String contactNumber;
@Schema(name ="开户银行")
private String depositBank;
@Schema(name ="银行账户")
private String bankAccount;
@Schema(name ="经营范围")
private String businessScope;
}

View File

@ -0,0 +1,48 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.TableName;
import com.xjrsoft.common.core.domain.base.AuditEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* <p>
* 岗位
* </p>
*
* @author tzx
* @since 2022-03-02
*/
@TableName("xjr_post")
@Tag(name = "Post对象", description = "岗位")
@Data
@EqualsAndHashCode(callSuper = false)
public class Post extends AuditEntity implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Schema(name ="名字")
private String name;
@Schema(name ="编码")
private String code;
@Schema(name ="父级")
private Long parentId;
@Schema(name ="排序号")
private Integer sortCode;
@Schema(name ="备注")
private String remark;
@Schema(name ="岗位所属组织id")
private Long deptId;
}

View File

@ -0,0 +1,56 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.TableName;
import com.xjrsoft.common.core.domain.base.AuditEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* <p>
* 角色
* </p>
*
* @author tzx
* @since 2022-03-02
*/
@TableName("xjr_role")
@Tag(name = "Role对象", description = "角色")
@Data
@EqualsAndHashCode(callSuper = false)
public class Role extends AuditEntity implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Schema(name ="名字")
private String name;
@Schema(name ="编码")
private String code;
public Role(){
}
public Role(String code,String name){
this.name=name;
this.code=code;
}
// @Schema(name ="数据权限")
// private Integer dataAuthType;
@Schema(name ="排序号")
private Integer sortCode;
@Schema(name ="备注")
private String remark;
@Schema(name = "租户id")
private Long tenantId;
}

View File

@ -0,0 +1,129 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.xjrsoft.common.core.domain.base.AuditEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 用户
* </p>
*
* @author tzx
* @since 2022-03-02
*/
@TableName("xjr_user")
@Tag(name = "User对象", description = "用户")
@Data
@EqualsAndHashCode(callSuper = false)
public class User extends AuditEntity implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Schema(name ="账户")
private String userName;
@Schema(name ="姓名")
private String name;
@Schema(name ="编号")
private String code;
@Schema(name ="昵称")
private String nickName;
@Schema(name ="密码")
private String password;
@Schema(name ="性别")
private Integer gender;
@Schema(name ="手机号")
private String mobile;
@Schema(name ="角色Id")
@TableField(exist = false)
private Long postId;
@Schema(name ="头像")
private String avatar;
@Schema(name ="邮箱")
private String email;
@Schema(name ="地址")
private String address;
@Schema(name ="经度")
private Double longitude;
@Schema(name ="纬度")
private Double latitude;
@Schema(name ="排序码")
private Integer sortCode;
@Schema(name ="备注")
private String remark;
@Schema(name ="部门")
@TableField(exist = false)
private Long departmentId;
@Schema(name ="微信号码")
private String wechatNumber;
@Schema(name ="qq号码")
private String qqNumber;
private LocalDateTime birthDate;
private Long tenantId;
private String tenantCode;
@Schema(name ="是否开启密码验证")
private Integer passwordAuthentication;
@Schema(name ="电话号码")
private String phoneNumber;
@Schema(name ="身份证号")
private String identityCardNumber;
@Schema(name ="政治面貌-数据字典id")
private Long politicsStatus;
@Schema(name ="行政职务-数据字典id")
private Long administrativePost;
@Schema(name ="行政职级-数据字典id")
private Long administrativeRank;
@Schema(name ="用户密级-数据字典id")
private Long secretLevel;
@Schema(name ="职称等级-数据字典id")
private Long professionalTitleGrade;
@Schema(name ="技术职务-数据字典id")
private Long technicalPosition;
@Schema(name ="管理职务-数据字典id")
private Long managerialPosition;
@Schema(name ="职业技能-数据字典id")
private Long vocationalSkill;
@Schema(name ="绑定ip")
private String bindIp;
}

View File

@ -0,0 +1,26 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
/**
* <p>
* 用户关联部门表
* </p>
*/
@TableName("xjr_user_dept_relation")
@Tag(name = "UserDeptRelation对象", description = "用户关联部门表")
@Data
public class UserDeptRelation {
private static final long serialVersionUID = 1L;
private Long id;
@Schema(name ="用户ID")
private Long userId;
@Schema(name ="部门id")
private Long deptId;
}

View File

@ -0,0 +1,31 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 用户关联岗位表
* </p>
*/
@TableName("xjr_user_post_relation")
@Tag(name = "UserPostRelation对象", description = "用户关联岗位表")
@Data
public class UserPostRelation implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Schema(name ="用户ID")
private Long userId;
@Schema(name ="岗位id")
private Long postId;
@Schema(name ="租户id")
private Long tenantId;
}

View File

@ -0,0 +1,44 @@
package com.xjrsoft.common.mybatis.model;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 用户关联角色表
* </p>
*
* @author tzx
* @since 2022-03-02
*/
@TableName("xjr_user_role_relation")
@Tag(name = "UserRoleRelation对象", description = "用户关联角色表")
@Data
public class UserRoleRelation implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Schema(name ="用户ID")
private Long userId;
@Schema(name ="角色ID")
private Long roleId;
public UserRoleRelation(){
}
public UserRoleRelation(Long userId,Long roleId){
this.userId=userId;
this.roleId=roleId;
}
@Schema(name ="租户id")
private Long tenantId;
}

View File

@ -0,0 +1,896 @@
package com.xjrsoft.common.mybatis.utils;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.xjrsoft.common.core.constant.GlobalConstant;
import com.xjrsoft.common.core.constant.StringPool;
import com.xjrsoft.common.core.enums.*;
import com.xjrsoft.common.core.exception.MyException;
import com.xjrsoft.common.mybatis.model.*;
import com.xjrsoft.common.redis.service.RedisUtil;
import lombok.SneakyThrows;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 数据权限工具类
*
* @Author: tzx
* @Date: 2023/3/1 10:22
*/
public class AuthorityUtil {
static RedisUtil redisUtil;
static {
redisUtil = SpringUtil.getBean(RedisUtil.class);
}
/**
* 根据表名 获取表达式解析
*
* @param tableName 表名
* @param tableAlias 表别名
* @return
*/
public static Expression getDataAuthExpressionByTableName(String tableName, String tableAlias) {
Expression dataAuthExpression = null;
List<DataAuthTableRelation> dataAuthTableRelations = redisUtil.get(GlobalConstant.DATA_AUTH_TABLE_RELATION_CACHE_KEY, new TypeReference<List<DataAuthTableRelation>>() {
});
//是否有设置权限
if (CollectionUtil.isEmpty(dataAuthTableRelations) || dataAuthTableRelations.stream().noneMatch(x -> x.getTableName().equals(tableName))) {
return null;
}
//找到当前表所关联的 数据权限
List<DataAuthTableRelation> tableDataAuths = dataAuthTableRelations.stream().filter(x -> x.getTableName().equals(tableName)).collect(Collectors.toList());
List<Long> allDataAuthId = tableDataAuths.stream().map(DataAuthTableRelation::getDataAuthId).collect(Collectors.toList());
List<DataAuth> dataAuths = redisUtil.get(GlobalConstant.DATA_AUTH_CACHE_KEY, new TypeReference<List<DataAuth>>() {
});
List<DataAuth> thisTableAuthDataList = dataAuths.stream().filter(x -> allDataAuthId.contains(x.getId())).collect(Collectors.toList());
List<DataAuthRelation> authRelationList = redisUtil.get(GlobalConstant.DATA_AUTH_RELATION_CACHE_KEY, new TypeReference<List<DataAuthRelation>>() {
});
List<DataAuthConfig> authConfigList = redisUtil.get(GlobalConstant.DATA_AUTH_CONFIG_CACHE_KEY, new TypeReference<List<DataAuthConfig>>() {
});
for (DataAuth dataAuth : thisTableAuthDataList) {
Expression expression = null;
List<Long> userIds = new ArrayList<>();
//如果是用户权限
if (dataAuth.getAuthType() == DataAuthTypeEnum.USER.getCode()) {
//找出有那些用户被赋值了 此数据权限
userIds = authRelationList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).map(DataAuthRelation::getObjectId).collect(Collectors.toList());
} else {
List<Long> roleIds = authRelationList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).map(DataAuthRelation::getObjectId).collect(Collectors.toList());
List<Long> currentRoleIdList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());
//如果当前登陆人不包含 这些 角色id 默认不添加数据权限
if (currentRoleIdList.stream().noneMatch(roleIds::contains)) {
continue;
}
userIds.add(StpUtil.getLoginIdAsLong());
}
//判断当前用户是否包含此数据权限
if (userIds.contains(StpUtil.getLoginIdAsLong())) {
//如果是简易模式
if (dataAuth.getAuthMethod() == DataAuthMethodEnum.SIMPLE.getCode()) {
//所有能查看的用户数据
List<Long> dataAuthSimpleUserId = getDataAuthSimpleUserId(dataAuth.getAuthScope());
List<Expression> expressionList = new ArrayList<>();
for (Long aLong : dataAuthSimpleUserId) {
expressionList.add(new LongValue(aLong));
}
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(buildColumn(tableAlias, GlobalConstant.AUTH_USER_ID));
inExpression.setRightItemsList(new ExpressionList(expressionList));
expression = inExpression;
}
//如果是自定义模式
else {
List<DataAuthConfig> thisDataAuthConfig = authConfigList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).collect(Collectors.toList());
expression = getDataAuthCustomExpression(thisDataAuthConfig, dataAuth, tableAlias);
}
// 组装数据权限取并集用or连接
if (dataAuthExpression == null) {
dataAuthExpression = expression;
} else {
dataAuthExpression = new OrExpression(dataAuthExpression, new Parenthesis(expression));
}
}
}
return dataAuthExpression;
}
/**
* 自定义模式 根据数据权限 获取 Expression
*
* @return
*/
@SneakyThrows
public static Expression getDataAuthCustomExpression(List<DataAuthConfig> configs, DataAuth dataAuth, String tableAlias) {
Expression dataAuthExpression = null;
if (StrUtil.isNotBlank(dataAuth.getAuthFormula())) {
StringBuilder resultExpresionString = new StringBuilder();
String[] split = dataAuth.getAuthFormula().split("");
for (int i = 0 ; i < split.length ;i++) {
//如果是数字 并且 包含当前
if (StrUtil.isNumeric(split[i])) {
Integer order = Convert.toInt(split[i]);
Optional<DataAuthConfig> configOptional = configs.stream().filter(x -> ObjectUtil.equals(x.getOrderNumber(), order)).findFirst();
if (!configOptional.isPresent()) {
continue;
}
Expression expression = getExpression(tableAlias, configOptional.get());
resultExpresionString.append(expression);
} else {
//有三种情况、and、or
if ((split[i].equals("a") && split[i+1].equals("n") && split[i+2].equals("d"))
|| (split[i].equals("A") && split[i+1].equals("N") && split[i+2].equals("D"))){
i = i + 2;
resultExpresionString.append(" and ");
} else if ((split[i].equals("o") && split[i+1].equals("r"))
|| (split[i].equals("O") && split[i+1].equals("R"))) {
i = i + 1;
resultExpresionString.append(" or ");
}else {
resultExpresionString.append(split[i]);
}
}
}
dataAuthExpression = CCJSqlParserUtil.parseExpression(resultExpresionString.toString());
}
// if (StrUtil.isNotBlank(dataAuth.getAuthFormula())) {
// String OrString = "or";
// String AndString = "and";
// //首先根据 or 切割 字符串
// String[] ors = dataAuth.getAuthFormula().toLowerCase().split(OrString);
//
// for (int i = 0; i < ors.length; i++) {
// //去除左右括号 再根据 and 切割
// String[] condition = ors[i].replace(StringPool.LEFT_BRACKET,StringPool.EMPTY).replace(StringPool.RIGHT_BRACKET,StringPool.EMPTY).toLowerCase().split(AndString);
// Expression expression = null;
// for (String index : condition) {
// Optional<DataAuthConfig> configOptional = configs.stream().filter(x -> ObjectUtil.equals(x.getOrderNumber(), Integer.valueOf(index.trim()))).findFirst();
//
// if (!configOptional.isPresent()) {
// continue;
// }
// expression = getExpression(tableAlias, expression, configOptional.get());
// }
// //如果是最后一个 不再需要拼接or
// if(i != ors.length - 1){
// //如果是第一个条件 直接赋值
// if(ObjectUtil.isNull(dataAuthExpression)){
// dataAuthExpression = new Parenthesis(expression);
// }
// else {
// dataAuthExpression = new OrExpression(dataAuthExpression, new Parenthesis(expression));
// }
// }
// else {
// dataAuthExpression = new AndExpression(dataAuthExpression,new Parenthesis(expression));
// }
//// //如果有括号
//// if (ors[i].contains(StringPool.LEFT_BRACKET) && ors[i].contains(StringPool.RIGHT_BRACKET)) {
////
//// }
////
//
// }
//
//// for (String or : ors) {
//// //如果有括号
//// if (or.contains(StringPool.LEFT_BRACKET) && or.contains(StringPool.RIGHT_BRACKET)) {
//// //去除左右括号 再根据 and 切割
//// String[] condition = or.replace(StringPool.LEFT_BRACKET,StringPool.EMPTY).replace(StringPool.LEFT_BRACKET,StringPool.EMPTY).toLowerCase().split(AndString);
//// Expression expression = null;
//// for (String index : condition) {
//// Optional<DataAuthConfig> configOptional = configs.stream().filter(x -> ObjectUtil.equals(x.getOrderNumber(), Integer.valueOf(index))).findFirst();
////
//// if (!configOptional.isPresent()) {
//// continue;
//// }
//// expression = getExpression(tableAlias, expression, configOptional.get());
//// }
////
//// dataAuthExpression = new Parenthesis(dataAuthExpression);
//// }
////
////
//// }
// }
else {
for (DataAuthConfig config : configs) {
dataAuthExpression = getExpression(tableAlias, dataAuthExpression, config);
}
}
return dataAuthExpression;
}
/**
* 拼接所有的权限表达式
* @param tableAlias
* @param dataAuthExpression
* @param config
* @return
*/
private static Expression getExpression(String tableAlias, Expression dataAuthExpression, DataAuthConfig config) {
Integer conditionType = config.getConditionType();
if (config.getFieldType() == DataAuthFieldTypeEnum.STRING.getCode()) {
//如果是第一个条件 直接赋值
if (ObjectUtil.isNull(dataAuthExpression)) {
dataAuthExpression = getConditionType(conditionType, tableAlias, config.getFieldName(), config.getFieldValue());
} else {
dataAuthExpression = new AndExpression(dataAuthExpression, getConditionType(conditionType, tableAlias, config.getFieldName(), config.getFieldValue()));
}
} else if (config.getFieldType() == DataAuthFieldTypeEnum.INT.getCode()) {
//如果是第一个条件 直接赋值
if (ObjectUtil.isNull(dataAuthExpression)) {
dataAuthExpression = getConditionTypeLong(conditionType, tableAlias, config.getFieldName(), config.getFieldValue());
} else {
dataAuthExpression = new AndExpression(dataAuthExpression, getConditionTypeLong(conditionType, tableAlias, config.getFieldName(), config.getFieldValue()));
}
} else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_USER_ID.getCode()) {//存在包含、不包含几种情况
User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
//如果是第一个条件 直接赋值
if (ObjectUtil.isNull(dataAuthExpression)) {
dataAuthExpression = getConditionType(conditionType, tableAlias, config.getFieldName(), user.getId().toString());
} else {
dataAuthExpression = new AndExpression(dataAuthExpression, getConditionType(conditionType, tableAlias, config.getFieldName(), user.getId().toString()));
}
} else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_DEP_ID.getCode()) {//只存在包含于,不包含于这两种,其它全部按包含于处理
InExpression inExpression = new InExpression();
List<Department> departmentList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
List<Expression> list = new ArrayList<>();
inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
for (Department department : departmentList) {
list.add(new StringValue(department.getId().toString()));
}
String Message = "该登陆人没有所属部门";
inExpression = getConditionTypeList(inExpression,conditionType,list,Message);
if (ObjectUtil.isNull(dataAuthExpression)) {
dataAuthExpression = inExpression;
} else {
dataAuthExpression = new AndExpression(dataAuthExpression, inExpression);
}
} else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_DEP_CHILD_ID.getCode()) {//只存在包含于,不包含于这两种,其它全部按包含于处理
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
List<Department> departmentList = redisUtil.get(GlobalConstant.DEP_CACHE_KEY, new TypeReference<List<Department>>() {
});
SaSession tokenSession = StpUtil.getTokenSession();
List<Department> currentDepartmentList = tokenSession.get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
List<Long> currentDepartmentIdList = currentDepartmentList.stream().map(Department::getId).collect(Collectors.toList());
List<Long> myAndOrgAndChildOrgUserId = getAllOrgChildId(ListUtil.toList(currentDepartmentIdList), departmentList);
myAndOrgAndChildOrgUserId.addAll(currentDepartmentIdList);
List<Expression> list = new ArrayList<>();
for (Long id : myAndOrgAndChildOrgUserId) {
list.add(new StringValue(id.toString()));
}
String Message = "该登陆人没有所属部门";
inExpression = getConditionTypeList(inExpression,conditionType,list,Message);
if (ObjectUtil.isNull(dataAuthExpression)) {
dataAuthExpression = inExpression;
} else {
dataAuthExpression = new AndExpression(dataAuthExpression, inExpression);
}
} else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_USER_NAME.getCode()) {
User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
//如果是第一个条件 直接赋值
if (ObjectUtil.isNull(dataAuthExpression)) {
dataAuthExpression = getConditionType(conditionType, tableAlias, config.getFieldName(), user.getUserName());
} else {
dataAuthExpression = new AndExpression(dataAuthExpression, getConditionType(conditionType, tableAlias, config.getFieldName(), user.getUserName()));
}
} else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_POST_ID.getCode()) {//只存在包含于,不包含于这两种,其它全部按包含于处理
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
List<Post> postList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_POST_LIST_KEY, new ArrayList<>());
List<Expression> list = new ArrayList<>();
for (Post post : postList) {
list.add(new StringValue(post.getId().toString()));
}
String Message = "该登陆人没有所属岗位";
inExpression = getConditionTypeList(inExpression,conditionType,list,Message);
if (ObjectUtil.isNull(dataAuthExpression)) {
dataAuthExpression = inExpression;
} else {
dataAuthExpression = new AndExpression(dataAuthExpression, inExpression);
}
} else {//只存在包含于,不包含于这两种,其它全部按包含于处理
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
List<Long> roleIdList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());
List<Expression> list = new ArrayList<>();
for (Long id : roleIdList) {
list.add(new LongValue(id));
}
String Message = "该登陆人没有所属角色";
inExpression = getConditionTypeList(inExpression,conditionType,list,Message);
if (ObjectUtil.isNull(dataAuthExpression)) {
dataAuthExpression = inExpression;
} else {
dataAuthExpression = new AndExpression(dataAuthExpression, inExpression);
}
}
return dataAuthExpression;
}
/**
* 只返回一个权限表达式
* @param tableAlias
* @param config
* @return
*/
private static Expression getExpression(String tableAlias, DataAuthConfig config) {
Integer conditionType = config.getConditionType();
if (config.getFieldType() == DataAuthFieldTypeEnum.STRING.getCode()) {
return getConditionType(conditionType, tableAlias, config.getFieldName(), config.getFieldValue());
} else if (config.getFieldType() == DataAuthFieldTypeEnum.INT.getCode()) {
return getConditionTypeLong(conditionType, tableAlias, config.getFieldName(), config.getFieldValue());
} else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_USER_ID.getCode()) {//存在包含、不包含两种情况
User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
return getConditionType(conditionType, tableAlias, config.getFieldName(), user.getId().toString());
} else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_DEP_ID.getCode()) {
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
List<Department> departmentList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
List<Expression> list = new ArrayList<>();
for (Department department : departmentList) {
list.add(new StringValue(department.getId().toString()));
}
String Message = "该登陆人没有所属部门";
return getConditionTypeList(inExpression,conditionType,list,Message);
} else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_DEP_CHILD_ID.getCode()) {
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
List<Department> departmentList = redisUtil.get(GlobalConstant.DEP_CACHE_KEY, new TypeReference<List<Department>>() {
});
SaSession tokenSession = StpUtil.getTokenSession();
List<Department> currentDepartmentList = tokenSession.get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
List<Long> currentDepartmentIdList = currentDepartmentList.stream().map(Department::getId).collect(Collectors.toList());
List<Long> myAndOrgAndChildOrgUserId = getAllOrgChildId(currentDepartmentIdList, departmentList);
myAndOrgAndChildOrgUserId.addAll(currentDepartmentIdList);
List<Expression> list = new ArrayList<>();
for (Long id : myAndOrgAndChildOrgUserId) {
list.add(new StringValue(id.toString()));
}
String Message = "该登陆人没有所属部门";
return getConditionTypeList(inExpression,conditionType,list,Message);
} else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_USER_NAME.getCode()) {
User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
return getConditionType(conditionType, tableAlias, config.getFieldName(), user.getUserName());
} else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_POST_ID.getCode()) {
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
List<Post> postList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_POST_LIST_KEY, new ArrayList<>());
List<Expression> list = new ArrayList<>();
for (Post post : postList) {
list.add(new StringValue(post.getId().toString()));
}
String Message = "该登陆人没有所属岗位";
return getConditionTypeList(inExpression,conditionType,list,Message);
} else {
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
List<Long> roleIdList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());
List<Expression> list = new ArrayList<>();
for (Long id : roleIdList) {
list.add(new StringValue(id.toString()));
}
String Message = "该登陆人没有所属角色";
return getConditionTypeList(inExpression,conditionType,list,Message);
}
}
public static InExpression getConditionTypeList(InExpression inExpression, Integer conditionType, List<Expression> list,String Message) {
if (conditionType == DataAuthConditionTypeEnum.NO_CONTAINED_IN.getCode()) {//包含于,其它全部按包含于处理
inExpression.setRightItemsList(new ExpressionList(list));
inExpression.setNot(true);
} else if (conditionType == DataAuthConditionTypeEnum.EQUAL_TO.getCode()) {//等于获取第一个部门id
if (list.size() > 0) {
inExpression.setRightItemsList(new ExpressionList(list.get(0)));
} else {
throw new MyException(Message);
}
} else if (conditionType == DataAuthConditionTypeEnum.NO_EQUAL_TO.getCode()) {//不等于获取第一个部门id
if (list.size() > 0) {
inExpression.setRightItemsList(new ExpressionList(list.get(0)));
inExpression.setNot(true);
} else {
throw new MyException(Message);
}
} else {
inExpression.setRightItemsList(new ExpressionList(list));
}
return inExpression;
}
public static Expression getConditionType(Integer conditionType, String tableAlias, String fieldName, String fieldValue) {
if (conditionType == DataAuthConditionTypeEnum.EQUAL_TO.getCode()) {
EqualsTo equalsTo = new EqualsTo(); //等于
equalsTo.setLeftExpression(buildColumn(tableAlias, fieldName));
equalsTo.setRightExpression(new StringValue(fieldValue));
return equalsTo;
} else if (conditionType == DataAuthConditionTypeEnum.GREATER_THAN.getCode()) {
GreaterThan greaterThan = new GreaterThan(); //大于
greaterThan.setLeftExpression(buildColumn(tableAlias, fieldName));
greaterThan.setRightExpression(new StringValue(fieldValue));
return greaterThan;
} else if (conditionType == DataAuthConditionTypeEnum.GREATER_THAN_EQUAL.getCode()) {
GreaterThanEquals greaterThanEquals = new GreaterThanEquals();//大于等于
greaterThanEquals.setLeftExpression(buildColumn(tableAlias, fieldName));
greaterThanEquals.setRightExpression(new StringValue(fieldValue));
return greaterThanEquals;
} else if (conditionType == DataAuthConditionTypeEnum.MINOR_THAN.getCode()) {
MinorThan minorThan = new MinorThan();//小于
minorThan.setLeftExpression(buildColumn(tableAlias, fieldName));
minorThan.setRightExpression(new StringValue(fieldValue));
return minorThan;
} else if (conditionType == DataAuthConditionTypeEnum.MINOR_THAN_EQUAL.getCode()) {
MinorThanEquals minorThanEquals = new MinorThanEquals();//小于等于
minorThanEquals.setLeftExpression(buildColumn(tableAlias, fieldName));
minorThanEquals.setRightExpression(new StringValue(fieldValue));
return minorThanEquals;
} else if (conditionType == DataAuthConditionTypeEnum.CONTAIN.getCode()) {//包含
LikeExpression likeExpression = new LikeExpression();
likeExpression.setLeftExpression(buildColumn(tableAlias, fieldName));
likeExpression.setRightExpression(new StringValue("%" + fieldValue + "%"));
return likeExpression;
} else if (conditionType == DataAuthConditionTypeEnum.CONTAINED_IN.getCode()) {//包含于
LikeExpression likeExpression = new LikeExpression();
likeExpression.setLeftExpression(new StringValue(fieldValue));
likeExpression.setRightExpression(buildColumn(tableAlias, fieldName));
return likeExpression;
} else if (conditionType == DataAuthConditionTypeEnum.NO_EQUAL_TO.getCode()) {//不等于
NotEqualsTo notEqualsTo = new NotEqualsTo();
notEqualsTo.setLeftExpression(buildColumn(tableAlias, fieldName));
notEqualsTo.setRightExpression(new StringValue(fieldValue));
return notEqualsTo;
} else if (conditionType == DataAuthConditionTypeEnum.NO_CONTAIN.getCode()) {//不包含
LikeExpression likeExpression = new LikeExpression();
likeExpression.setLeftExpression(buildColumn(tableAlias, fieldName));
likeExpression.setNot(true);
likeExpression.setRightExpression(new StringValue("%" + fieldValue + "%"));
return likeExpression;
} else if (conditionType == DataAuthConditionTypeEnum.NO_CONTAINED_IN.getCode()) {//不包含于
LikeExpression likeExpression = new LikeExpression();
likeExpression.setNot(true);
likeExpression.setLeftExpression(new StringValue(fieldValue));
likeExpression.setRightExpression(buildColumn(tableAlias, fieldName));
return likeExpression;
} else {
throw new MyException("条件不成立");
}
}
public static Expression getConditionTypeLong(Integer conditionType, String tableAlias, String fieldName, String fieldValue) {
if (conditionType == DataAuthConditionTypeEnum.EQUAL_TO.getCode()) {
EqualsTo equalsTo = new EqualsTo(); //等于
equalsTo.setLeftExpression(buildColumn(tableAlias, fieldName));
equalsTo.setRightExpression(new LongValue(fieldValue));
return equalsTo;
} else if (conditionType == DataAuthConditionTypeEnum.GREATER_THAN.getCode()) {
GreaterThan greaterThan = new GreaterThan(); //大于
greaterThan.setLeftExpression(buildColumn(tableAlias, fieldName));
greaterThan.setRightExpression(new LongValue(fieldValue));
return greaterThan;
} else if (conditionType == DataAuthConditionTypeEnum.GREATER_THAN_EQUAL.getCode()) {
GreaterThanEquals greaterThanEquals = new GreaterThanEquals();//大于等于
greaterThanEquals.setLeftExpression(buildColumn(tableAlias, fieldName));
greaterThanEquals.setRightExpression(new LongValue(fieldValue));
return greaterThanEquals;
} else if (conditionType == DataAuthConditionTypeEnum.MINOR_THAN.getCode()) {
MinorThan minorThan = new MinorThan();//小于
minorThan.setLeftExpression(buildColumn(tableAlias, fieldName));
minorThan.setRightExpression(new LongValue(fieldValue));
return minorThan;
} else if (conditionType == DataAuthConditionTypeEnum.MINOR_THAN_EQUAL.getCode()) {
MinorThanEquals minorThanEquals = new MinorThanEquals();//小于等于
minorThanEquals.setLeftExpression(buildColumn(tableAlias, fieldName));
minorThanEquals.setRightExpression(new LongValue(fieldValue));
return minorThanEquals;
} else if (conditionType == DataAuthConditionTypeEnum.CONTAIN.getCode()) {//包含
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(buildColumn(tableAlias, fieldName));
List<Expression> list = new ArrayList<>();
list.add(new LongValue(fieldValue));
inExpression.setRightItemsList(new ExpressionList(list));
// LikeExpression likeExpression = new LikeExpression();
// likeExpression.setLeftExpression(buildColumn(tableAlias, fieldName));
// likeExpression.setRightExpression(new StringValue("%" + fieldValue + "%"));
return inExpression;
} else if (conditionType == DataAuthConditionTypeEnum.CONTAINED_IN.getCode()) {//包含于
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(new LongValue(fieldValue));
List<Expression> list = new ArrayList<>();
list.add(buildColumn(tableAlias, fieldName));
inExpression.setRightItemsList(new ExpressionList(list));
return inExpression;
} else if (conditionType == DataAuthConditionTypeEnum.NO_EQUAL_TO.getCode()) {//不等于
NotEqualsTo notEqualsTo = new NotEqualsTo();
notEqualsTo.setLeftExpression(buildColumn(tableAlias, fieldName));
notEqualsTo.setRightExpression(new LongValue(fieldValue));
return notEqualsTo;
} else if (conditionType == DataAuthConditionTypeEnum.NO_CONTAIN.getCode()) {//不包含
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(buildColumn(tableAlias, fieldName));
List<Expression> list = new ArrayList<>();
list.add(new LongValue(fieldValue));
inExpression.setRightItemsList(new ExpressionList(list));
inExpression.setNot(true);
return inExpression;
} else if (conditionType == DataAuthConditionTypeEnum.NO_CONTAINED_IN.getCode()) {//不包含于
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(new LongValue(fieldValue));
List<Expression> list = new ArrayList<>();
list.add(buildColumn(tableAlias, fieldName));
inExpression.setRightItemsList(new ExpressionList(list));
inExpression.setNot(true);
return inExpression;
} else {
throw new MyException("条件不成立");
}
}
/**
* 构建Column
*
* @param tableAlias 表别名
* @param columnName 字段名称
* @return 带表别名字段
*/
public static Column buildColumn(String tableAlias, String columnName) {
if (StrUtil.isNotEmpty(tableAlias)) {
columnName = tableAlias + StringPool.DOT + columnName;
}
return new Column(columnName);
}
public static List<Long> getDataAuthByTableName(String tableName) {
List<Long> result = new ArrayList<>();
List<DataAuthTableRelation> dataAuthTableRelations = redisUtil.get(GlobalConstant.DATA_AUTH_TABLE_RELATION_CACHE_KEY, new TypeReference<List<DataAuthTableRelation>>() {
});
//是否有设置权限
if (dataAuthTableRelations.stream().noneMatch(x -> x.getTableName().equals(tableName))) {
return result;
}
//找到当前表所关联的 数据权限
List<DataAuthTableRelation> tableDataAuths = dataAuthTableRelations.stream().filter(x -> x.getTableName().equals(tableName)).collect(Collectors.toList());
List<Long> allDataAuthId = tableDataAuths.stream().map(DataAuthTableRelation::getDataAuthId).collect(Collectors.toList());
List<DataAuth> dataAuths = redisUtil.get(GlobalConstant.DATA_AUTH_CACHE_KEY, new TypeReference<List<DataAuth>>() {
});
List<DataAuth> thisTableAuthDataList = dataAuths.stream().filter(x -> allDataAuthId.contains(x.getId())).collect(Collectors.toList());
List<DataAuthRelation> authRelationList = redisUtil.get(GlobalConstant.DATA_AUTH_RELATION_CACHE_KEY, new TypeReference<List<DataAuthRelation>>() {
});
for (DataAuth dataAuth : thisTableAuthDataList) {
//如果是用户权限
if (dataAuth.getAuthType() == DataAuthTypeEnum.USER.getCode()) {
//找出有那些用户被赋值了 此数据权限
List<Long> userIds = authRelationList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).map(DataAuthRelation::getObjectId).collect(Collectors.toList());
//判断当前用户是否包含此数据权限
if (userIds.contains(StpUtil.getLoginIdAsLong())) {
//如果是简易模式
if (dataAuth.getAuthMethod() == DataAuthMethodEnum.CUSTOM.getCode()) {
List<Long> dataAuthSimpleUserId = getDataAuthSimpleUserId(dataAuth.getAuthScope());
result.addAll(dataAuthSimpleUserId);
}
//如果是自定义模式
else {
}
}
}
}
return result;
}
/**
* 获取简易模式的所有用户id
*
* @return
*/
private static List<Long> getDataAuthSimpleUserId(Integer authScope) {
DataAuthScopeEnum enumAt = EnumUtil.getEnumAt(DataAuthScopeEnum.class, authScope);
switch (enumAt) {
case MY:
return ListUtil.toList(StpUtil.getLoginIdAsLong());
case MY_AND_POST:
return getMyAndPostUserId();
case MY_AND_CHILD_POST:
return getMyAndChildPostUserId();
case MY_AND_POST_AND_CHILD_POST:
return getMyAndPostAndChildPostUserId();
case MY_AND_ORG:
return getMyAndOrgUserId();
case MY_AND_CHILD_ORG:
return getMyAndChildOrgUserId();
case MY_AND_ORG_AND_CHILD_ORG:
return getMyAndOrgAndChildOrgUserId();
default:
return getRoleUserId();
}
}
/**
* 获取同岗位的用户id
*
* @return
*/
private static List<Long> getMyAndPostUserId() {
List<UserPostRelation> userRelationList = redisUtil.get(GlobalConstant.USER_POST_RELATION_CACHE_KEY, new TypeReference<List<UserPostRelation>>() {
});
SaSession tokenSession = StpUtil.getTokenSession();
List<Post> postList = tokenSession.get(GlobalConstant.LOGIN_USER_POST_LIST_KEY, new ArrayList<>(0));
List<Long> postIdList = postList.stream().map(Post::getId).collect(Collectors.toList());
return userRelationList.stream()
.filter(x -> postIdList.contains(x.getPostId()))
.map(UserPostRelation::getUserId).collect(Collectors.toList());
}
/**
* 获取同岗位的用户id
*
* @return
*/
private static List<Long> getMyAndChildPostUserId() {
List<UserPostRelation> userRelationList = redisUtil.get(GlobalConstant.USER_POST_RELATION_CACHE_KEY, new TypeReference<List<UserPostRelation>>() {
});
List<Post> postList = redisUtil.get(GlobalConstant.POST_CACHE_KEY, new TypeReference<List<Post>>() {
});
SaSession tokenSession = StpUtil.getTokenSession();
List<Post> currentPostList = tokenSession.get(GlobalConstant.LOGIN_USER_POST_LIST_KEY, new ArrayList<>(0));
List<Long> postIdList = currentPostList.stream().map(Post::getId).collect(Collectors.toList());
List<Long> resultList = new ArrayList<>();
//如果有下级 则使用递归 找到所有下级post 求出所有用户id
if (postList.stream().anyMatch(x -> postIdList.contains(x.getParentId()))) {
List<Long> allPostId = getAllPostChildId(postIdList, postList);
resultList.addAll(userRelationList.stream().filter(user -> allPostId.contains(user.getPostId())).map(UserPostRelation::getUserId).collect(Collectors.toList()));
}
//当前登录人id
resultList.add(StpUtil.getLoginIdAsLong());
return resultList;
}
private static List<Long> getMyAndPostAndChildPostUserId() {
List<Long> result = new ArrayList<>();
result.addAll(getMyAndPostUserId());
result.addAll(getMyAndChildPostUserId());
return result;
}
private static List<Long> getAllPostChildId(List<Long> postIds, List<Post> postList) {
List<Long> resultList = new ArrayList<>();
for (Long postId : postIds) {
for (Post post : postList) {
if (postId.equals(post.getParentId())) {
resultList.add(post.getId());
}
}
}
if (CollectionUtils.isNotEmpty(resultList)) {
resultList.addAll(getAllPostChildId(resultList, postList));
}
return resultList;
}
private static List<Long> getAllOrgChildId(List<Long> depIds, List<Department> departmentList) {
List<Long> resultList = new ArrayList<>();
for (Long depId : depIds) {
for (Department department : departmentList) {
if (depId.equals(department.getParentId())) {
resultList.add(department.getId());
}
}
}
if (CollectionUtils.isNotEmpty(resultList)) {
resultList.addAll(getAllOrgChildId(resultList, departmentList));
}
return resultList;
}
/**
* 获取同机构/部门的数据
*
* @return
*/
public static List<Long> getMyAndOrgUserId() {
List<UserDeptRelation> userDeptRelations = redisUtil.get(GlobalConstant.USER_DEPT_RELATION_CACHE_KEY, new TypeReference<List<UserDeptRelation>>() {
});
SaSession tokenSession = StpUtil.getTokenSession();
List<Department> departmentList = tokenSession.get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
List<Long> departmentIdList = departmentList.stream().map(Department::getId).collect(Collectors.toList());
return userDeptRelations.stream()
.filter(x -> departmentIdList.contains(x.getDeptId()))
.map(UserDeptRelation::getUserId).collect(Collectors.toList());
}
/**
* 获取下属机构数据的用户id
*
* @return
*/
private static List<Long> getMyAndChildOrgUserId() {
List<Long> resultList = new ArrayList<>();
List<UserDeptRelation> userDeptRelations = redisUtil.get(GlobalConstant.USER_DEPT_RELATION_CACHE_KEY, new TypeReference<List<UserDeptRelation>>() {
});
List<Department> departmentList = redisUtil.get(GlobalConstant.DEP_CACHE_KEY, new TypeReference<List<Department>>() {
});
SaSession tokenSession = StpUtil.getTokenSession();
List<Department> currentDepartmentList = tokenSession.get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
List<Long> currentDepartmentIdList = currentDepartmentList.stream().map(Department::getId).collect(Collectors.toList());
//如果有下级 则使用递归 找到所有下级post 求出所有用户id
if (departmentList.stream().anyMatch(x -> currentDepartmentIdList.contains(x.getParentId()))) {
List<Long> allChildIdList = getAllOrgChildId(currentDepartmentIdList, departmentList);
resultList.addAll(userDeptRelations.stream().filter(user -> allChildIdList.contains(user.getDeptId())).map(UserDeptRelation::getUserId).collect(Collectors.toList()));
}
//如果没有下级 直接使用当前登陆人岗位
resultList.add(StpUtil.getLoginIdAsLong());
return resultList;
}
/**
* 获取当前机构 和下属机构
*
* @return
*/
private static List<Long> getMyAndOrgAndChildOrgUserId() {
List<Long> result = new ArrayList<>();
result.addAll(getMyAndOrgUserId());
result.addAll(getMyAndChildOrgUserId());
return result;
}
/**
* 获取同角色
*
* @return
*/
private static List<Long> getRoleUserId() {
List<UserRoleRelation> userRoleRelationList = redisUtil.get(GlobalConstant.USER_ROLE_RELATION_CACHE_KEY, new TypeReference<List<UserRoleRelation>>() {
});
List<Long> roleIdList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());
return userRoleRelationList.stream().filter(r -> roleIdList.contains(r.getRoleId())).map(UserRoleRelation::getUserId).collect(Collectors.toList());
}
/**
* 根据 tableName 生成 expression 给自定义表单 生成sql
*
* @param tableName 表名
* @return
*/
// public static Expression getDataAuthEntityByTableName(String tableName) {
// SelectUtils.buildSelectFromTable(new Table(tableName));
//
// List<DataAuthTableRelation> dataAuthTableRelations = redisUtil.get(GlobalConstant.DATA_AUTH_TABLE_RELATION_CACHE_KEY, new TypeReference<List<DataAuthTableRelation>>() {
// });
//
// //是否有设置权限
// if (dataAuthTableRelations.stream().noneMatch(x -> x.getTableName().equals(tableName))) {
// return where;
// }
//
// //找到当前表所关联的 数据权限
// List<DataAuthTableRelation> tableDataAuths = dataAuthTableRelations.stream().filter(x -> x.getTableName().equals(tableName)).collect(Collectors.toList());
//
// List<Long> allDataAuthId = tableDataAuths.stream().map(DataAuthTableRelation::getDataAuthId).collect(Collectors.toList());
// List<DataAuth> dataAuths = redisUtil.get(GlobalConstant.DATA_AUTH_CACHE_KEY, new TypeReference<List<DataAuth>>() {
// });
//
// List<DataAuth> thisTableAuthDataList = dataAuths.stream().filter(x -> allDataAuthId.contains(x.getId())).collect(Collectors.toList());
//
// List<DataAuthRelation> authRelationList = redisUtil.get(GlobalConstant.DATA_AUTH_RELATION_CACHE_KEY, new TypeReference<List<DataAuthRelation>>() {
// });
//
// List<DataAuthConfig> authConfigList = redisUtil.get(GlobalConstant.DATA_AUTH_CONFIG_CACHE_KEY, new TypeReference<List<DataAuthConfig>>() {
// });
//
// for (DataAuth dataAuth : thisTableAuthDataList) {
// List<Long> userIds = new ArrayList<>();
// //如果是用户权限
// if (dataAuth.getAuthType() == DataAuthTypeEnum.USER.getCode()) {
// //找出有那些用户被赋值了 此数据权限
// userIds = authRelationList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).map(DataAuthRelation::getObjectId).collect(Collectors.toList());
// } else {
// List<Long> roleIds = authRelationList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).map(DataAuthRelation::getObjectId).collect(Collectors.toList());
//
// List<Role> roleList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new ArrayList<>());
//
// //如果当前登陆人不包含 这些 角色id 默认不添加数据权限
// if (roleList.stream().map(Role::getId).noneMatch(roleIds::contains)) {
// continue;
// }
// }
// //判断当前用户是否包含此数据权限
// if (userIds.contains(StpUtil.getLoginIdAsLong())) {
//
// //如果是简易模式
// if (dataAuth.getAuthMethod() == DataAuthMethodEnum.SIMPLE.getCode()) {
// //所有能查看的用户数据
// List<Long> dataAuthSimpleUserId = getDataAuthSimpleUserId(dataAuth.getAuthScope());
//
//// where.set(GlobalConstant.AUTH_USER_ID, new Condition(GlobalConstant.AUTH_USER_ID, "in", dataAuthSimpleUserId));
// where.set(GlobalConstant.AUTH_USER_ID, dataAuthSimpleUserId);
//
// }
// //如果是自定义模式
// else {
// List<DataAuthConfig> thisDataAuthConfig = authConfigList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).collect(Collectors.toList());
// }
//
// }
// }
//
// return where;
// }
}

View File

@ -0,0 +1,79 @@
package com.xjrsoft.common.mybatis.utils;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xjrsoft.common.core.constant.GlobalConstant;
import com.xjrsoft.common.core.domain.page.PageInput;
import com.xjrsoft.common.core.domain.page.PageOutput;
import com.xjrsoft.common.core.xss.SQLFilter;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @Author: tzx
* @Date:2022/3/7 14:51
*/
public class ConventPage {
public ConventPage() {
}
/**
* 分页入参 转换为 IPage
*/
public static <T> IPage<T> getPage(@NotNull PageInput input) {
Page<T> page = new Page<>(input.getLimit(), input.getSize());
String orderField = SQLFilter.sqlInject(StrUtil.toUnderlineCase(input.getField()));
String order = SQLFilter.sqlInject(StrUtil.toUnderlineCase(input.getOrder()));
if (StrUtil.equalsIgnoreCase(GlobalConstant.ORDER_DESC, order)) {
page.addOrder(OrderItem.desc(orderField));
} else {
page.addOrder(OrderItem.asc(orderField));
}
return page;
}
/**
* 根据查询出来得分页 转换为 pageoutput
*/
public static <T> PageOutput<T> getPageOutput(IPage<T> page) {
PageOutput<T> output = new PageOutput<>();
output.setTotal(Convert.toInt(page.getTotal()));
output.setList(page.getRecords());
return output;
}
/**
* 根据查询出来得分页 转换为 pageoutput 并且重新隐射为vo
*
* @param page 查出来得page
* @param clazz vo类型
*/
public static <T> PageOutput<T> getPageOutput(IPage<?> page, Class<T> clazz) {
PageOutput<T> output = new PageOutput<>();
output.setTotal(Convert.toInt(page.getTotal()));
List<T> ts = BeanUtil.copyToList(page.getRecords(), clazz);
output.setList(ts);
return output;
}
/**
* 分页入参 转换为 IPage
*/
public static String getOrder(@NotNull String order) {
String orderString = SQLFilter.sqlInject(StrUtil.toUnderlineCase(order));
if (StrUtil.equalsIgnoreCase(GlobalConstant.ORDER_DESC, orderString)) {
return "desc";
} else {
return "asc";
}
}
}

View File

@ -0,0 +1,675 @@
package com.xjrsoft.common.mybatis.utils;
import cn.hutool.core.util.PageUtil;
import cn.hutool.db.DbUtil;
import cn.hutool.db.Page;
import cn.hutool.db.ds.simple.SimpleDataSource;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
import com.xjrsoft.common.core.constant.GlobalConstant;
import com.xjrsoft.common.core.enums.MySqlFieldsType;
import com.xjrsoft.common.core.enums.OracleFieldsType;
import com.xjrsoft.common.core.enums.PostgreSqlFieldsType;
import com.xjrsoft.common.core.enums.SqlServerFieldsType;
import com.xjrsoft.common.generate.model.TableFieldConfig;
import com.xjrsoft.common.generate.model.TableStructureConfig;
import com.xjrsoft.tenant.config.TenantConfig;
import com.xjrsoft.common.core.enums.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
/**
* @title: 数据源工具类
* @Author tzx
* @Date: 2022/4/17 14:55
* @Version 1.0
*/
@Slf4j
public class DatasourceUtil {
private static final TenantConfig tenantConfig;
static {
tenantConfig = SpringUtil.getBean(TenantConfig.class);
}
/**
* 获取主数据源
*
* @return
*/
public static DataSource getDatasourceMaster() {
DynamicRoutingDataSource dynamicRoutingDataSource = SpringUtil.getBean(DynamicRoutingDataSource.class);
return dynamicRoutingDataSource.getDataSource(GlobalConstant.DEFAULT_DATASOURCE_KEY);
}
/**
* 获取数据源
*
* @return
*/
public static DataSource getDataSource(String id) {
DynamicRoutingDataSource dynamicRoutingDataSource = SpringUtil.getBean(DynamicRoutingDataSource.class);
try {
return dynamicRoutingDataSource.getDataSource(id);
} catch (Exception e) {
throw new RuntimeException("获取数据源失败: " + id);
}
}
public static DbType getDataSourceMasterDbType() {
DynamicDataSourceProperties dynamicDataSourceProperties = SpringUtil.getBean(DynamicDataSourceProperties.class);
DataSourceProperty datasource = dynamicDataSourceProperties.getDatasource().get(dynamicDataSourceProperties.getPrimary());
return JdbcUtils.getDbType(datasource.getUrl());
}
/**
* 关闭链接
*
* @return
*/
@SneakyThrows
public static void close(Connection connection, ResultSet resultSet) {
if (resultSet != null) {
resultSet.close();
}
if (connection != null) {
connection.close();
}
}
/**
* 构建分页查询sql
*
* @param sql
* @param page
* @return
*/
public static String wrapperPageSql(String sql, Page page, DbType dbType) {
switch (dbType) {
case MYSQL:
return wrapperPageSqlForMysql(sql, page);
case ORACLE:
case ORACLE_12C:
return wrapperPageSqlForOracle(sql, page);
case SQL_SERVER:
return wrapperPageSqlForSqlServer(sql, page);
case POSTGRE_SQL:
return wrapperPageSqlForPostgreSql(sql, page);
case DM:
return wrapperPageSqlForDm(sql, page);
case DB2:
return wrapperPageSqlForDb2(sql, page);
case KINGBASE_ES:
return wrapperPageSqlForKingBaseEs(sql, page);
case GAUSS:
return wrapperPageSqlForGauss(sql, page);
default:
return sql;
}
}
private static String wrapperPageSqlForMysql(String sql, Page page) {
return "select * from (" + sql + ") t" + " limit " + PageUtil.getStart(page.getPageNumber(), page.getPageSize()) + "," +page.getPageSize();
}
private static String wrapperPageSqlForOracle(String sql, Page page) {
return "select * from ( SELECT row_.*, rownum rownum_ from ( " + sql + " ) row_ where rownum <= " + PageUtil.getStart(page.getPageNumber(), page.getPageSize()) + ") table_alias where table_alias.rownum_ >" + PageUtil.getEnd(page.getPageNumber(), page.getPageSize());
}
private static String wrapperPageSqlForSqlServer(String sql, Page page) {
return "select * FROM ( " + sql + " ) t ORDER BY current_timestamp offset " + PageUtil.getStart(page.getPageNumber(), page.getPageSize()) + " rows fetch next " + PageUtil.getEnd(page.getPageNumber(), page.getPageSize()) + " rows only";
}
private static String wrapperPageSqlForPostgreSql(String sql, Page page) {
return "select * FROM ( " + sql + " ) t limit " + page.getPageNumber() + " offset " + page.getPageSize();
}
private static String wrapperPageSqlForDm(String sql, Page page) {
return "select * from (" + sql + ") t" + " limit " + PageUtil.getStart(page.getPageNumber(), page.getPageSize()) + "," + PageUtil.getEnd(page.getPageNumber(), page.getPageSize());
}
private static String wrapperPageSqlForDb2(String sql, Page page) {
return "select row_num() over() as rownum,* from ( " + sql + " ) where rownum > " + PageUtil.getStart(page.getPageNumber(), page.getPageSize()) + " and rownum < " + PageUtil.getEnd(page.getPageNumber(), page.getPageSize());
}
private static String wrapperPageSqlForKingBaseEs(String sql, Page page) {
return "select * FROM ( " + sql + " ) t limit " + page.getPageNumber() + " offset " + page.getPageSize();
}
private static String wrapperPageSqlForGauss(String sql, Page page) {
return "select * FROM ( " + sql + " ) t limit " + page.getPageNumber() + " offset " + page.getPageSize();
}
private static String wrapperPageCount(String sql, Page page) {
return "select count(*) from (" + sql + ") t";
}
/**
* 构建测试sql
*
* @return
*/
public static String wrapperTestSql(DbType dbType) {
switch (dbType) {
case ORACLE:
case ORACLE_12C:
return "SELECT 1 FROM DUAL";
default:
return "select 1";
}
}
/**
* 构建测试sql
*
* @return
*/
public static String wrapperDropSql(String tableName) {
return "drop table " + tableName;
}
/**
* 构建建表sql语句
*
* @param tableStructureConfigs
* @return
*/
public static List<String> wrapperCreateTableSql(List<TableStructureConfig> tableStructureConfigs, DbType dbType) {
switch (dbType) {
case ORACLE:
case ORACLE_12C:
case DM:
return wrapperCreateTableSqlForOracle(tableStructureConfigs, dbType);
case DB2:
return wrapperCreateTableSqlForDB2(tableStructureConfigs);
case SQL_SERVER2005:
case SQL_SERVER:
return wrapperCreateTableSqlForSqlServer(tableStructureConfigs);
case POSTGRE_SQL:
case KINGBASE_ES:
case GAUSS:
return wrapperCreateTableSqlForPostgreSql(tableStructureConfigs);
default:
return wrapperCreateTableSqlForMysql(tableStructureConfigs);
}
}
private static List<String> wrapperCreateTableSqlForMysql(List<TableStructureConfig> tableStructureConfigs) {
List<String> sqls = new ArrayList<>();
//遍历所有表配置
for (TableStructureConfig tableStructureConfig : tableStructureConfigs) {
// 创建新表和覆盖旧表才需要创建表
Integer operator = tableStructureConfig.getOperator();
if (operator == 1) {
continue;
}
if (operator == 3) {
sqls.add(wrapperDropSql(tableStructureConfig.getTableName()));
}
StringBuilder sb = new StringBuilder();
sb.append("CREATE TABLE `").append(tableStructureConfig.getTableName()).append("` ( \n");
sb.append(" `").append(GlobalConstant.DEFAULT_PK).append("` bigint NOT NULL, \n");
List<TableFieldConfig> tableFieldConfigs = tableStructureConfig.getTableFieldConfigs();
//遍历当前表配置的 字段配置
for (TableFieldConfig tableFieldConfig : tableFieldConfigs) {
MySqlFieldsType fieldType = MySqlFieldsType.getFieldType(tableFieldConfig.getFieldType());
String type = fieldType.getType();
switch (fieldType) {
//普通文本
case VARCHAR:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(").append(tableFieldConfig.getFieldLength()).append(") COMMENT '" + tableFieldConfig.getFieldComment() + "', \n");
break;
//长文本
case VARCHARMAX:
//数字
case INT:
case FLOAT:
//日期
case DATE:
//日期时间
case DATETIME:
//长数字
case LONG:
//时间
case TIME:
sb.append(" `").append(tableFieldConfig.getFieldName()).append("` ").append(type).append(" COMMENT '").append(tableFieldConfig.getFieldComment()).append("', \n");
break;
default:
sb.append(" `").append(tableFieldConfig.getFieldName()).append("` ").append(type).append("(").append(GlobalConstant.DEFAULT_TEXT_LENGTH).append(") COMMENT '").append(tableFieldConfig.getFieldComment()).append("', \n");
break;
}
}
//如果不是主表 默认需要新增主表关联字段 用于关联主表 默认字段名为 parent + _id
if(!tableStructureConfig.getIsMain()){
sb.append(" `").append(GlobalConstant.DEFAULT_FK).append("` bigint , \n");
}
if (BooleanUtils.isTrue(tenantConfig.getEnabled())) {
sb.append(" `").append(tenantConfig.getTenantField()).append("` bigint , \n");
}
sb.append(" PRIMARY KEY (`").append(GlobalConstant.DEFAULT_PK).append("`) \n");
sb.append(") ENGINE=`InnoDB` DEFAULT CHARACTER SET utf8mb4 COMMENT='").append(tableStructureConfig.getTableComment()).append("';\n");
sqls.add(sb.toString());
}
return sqls;
}
private static List<String> wrapperCreateTableSqlForOracle(List<TableStructureConfig> tableStructureConfigs, DbType dbType) {
List<String> sqls = new ArrayList<>();
//遍历所有表配置
for (TableStructureConfig tableStructureConfig : tableStructureConfigs) {
// 创建新表和覆盖旧表才需要创建表
Integer operator = tableStructureConfig.getOperator();
if (operator == 1) {
continue;
}
if (operator == 3) {
sqls.add(wrapperDropSql(tableStructureConfig.getTableName()));
}
StringBuilder sb = new StringBuilder();
sb.append("CREATE TABLE ").append(tableStructureConfig.getTableName()).append(" ( \n");
sb.append(" ").append(GlobalConstant.DEFAULT_PK).append(" NUMBER(20, 0) NOT NULL, \n");
List<TableFieldConfig> tableFieldConfigs = tableStructureConfig.getTableFieldConfigs();
//遍历当前表配置的 字段配置
for (TableFieldConfig tableFieldConfig : tableFieldConfigs) {
OracleFieldsType fieldType = OracleFieldsType.getFieldType(tableFieldConfig.getFieldType());
String type = fieldType.getType();
switch (fieldType) {
//普通文本
case VARCHAR:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(").append(tableFieldConfig.getFieldLength()).append("), \n");
break;
//数字
case INT:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(11, 0), \n");
break;
//长数字
case LONG:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(20, 0), \n");
break;
//小数
case FLOAT:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(20, 10), \n");
break;
//长文本
case VARCHARMAX:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(2000), \n");
break;
//日期
case DATE:
case DATETIME:
// 时间
case TIME:
if (dbType == DbType.DM && fieldType == OracleFieldsType.TIME) {
sb.append(tableFieldConfig.getFieldName()).append(" ").append("TIME").append(", \n");
} else {
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append(", \n");
}
break;
default:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(").append(GlobalConstant.DEFAULT_TEXT_LENGTH).append("), \n");
break;
}
}
//如果不是主表 默认需要新增主表关联字段 用于关联主表 默认字段名为 parent + _id
if(!tableStructureConfig.getIsMain()){
sb.append(" ").append(GlobalConstant.DEFAULT_FK).append(" NUMBER(20, 0), \n");
}
if (BooleanUtils.isTrue(tenantConfig.getEnabled())) {
sb.append(" ").append(tenantConfig.getTenantField()).append(" NUMBER(20,0) , \n");
}
sb.append(" PRIMARY KEY (").append(GlobalConstant.DEFAULT_PK).append(") \n");
sb.append(") \n");
sqls.add(sb.toString());
}
for (TableStructureConfig tableStructureConfig : tableStructureConfigs) {
List<TableFieldConfig> tableFieldConfigs = tableStructureConfig.getTableFieldConfigs();
//遍历当前表配置的 字段配置
for (TableFieldConfig tableFieldConfig : tableFieldConfigs) {
sqls.add("COMMENT ON COLUMN " + tableStructureConfig.getTableName() + "." + tableFieldConfig.getFieldName() + " IS '" + tableFieldConfig.getFieldComment() + "'");
}
}
return sqls;
}
private static List<String> wrapperCreateTableSqlForDB2(List<TableStructureConfig> tableStructureConfigs) {
List<String> sqls = new ArrayList<>();
//遍历所有表配置
for (TableStructureConfig tableStructureConfig : tableStructureConfigs) {
// 创建新表和覆盖旧表才需要创建表
Integer operator = tableStructureConfig.getOperator();
if (operator == 1) {
continue;
}
if (operator == 3) {
sqls.add(wrapperDropSql(tableStructureConfig.getTableName()));
}
StringBuilder sb = new StringBuilder();
sb.append("CREATE TABLE ").append(tableStructureConfig.getTableName()).append(" ( \n");
sb.append(" ").append(GlobalConstant.DEFAULT_PK).append(" BIGINT NOT NULL, \n");
List<TableFieldConfig> tableFieldConfigs = tableStructureConfig.getTableFieldConfigs();
//遍历当前表配置的 字段配置
for (TableFieldConfig tableFieldConfig : tableFieldConfigs) {
DB2FieldsType fieldType = DB2FieldsType.getFieldType(tableFieldConfig.getFieldType());
String type = fieldType.getType();
switch (fieldType) {
//普通文本
case VARCHAR:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(").append(tableFieldConfig.getFieldLength()).append("), \n");
break;
//数字
case INT:
//长数字
case LONG:
//小数
case FLOAT:
//长文本
case VARCHARMAX:
//日期
case DATE:
case DATETIME:
// 时间
case TIME:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append(", \n");
break;
default:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(").append(GlobalConstant.DEFAULT_TEXT_LENGTH).append("), \n");
break;
}
}
//如果不是主表 默认需要新增主表关联字段 用于关联主表 默认字段名为 parent + _id
if(!tableStructureConfig.getIsMain()){
sb.append(" ").append(GlobalConstant.DEFAULT_FK).append(" BIGINT, \n");
}
sb.append(" PRIMARY KEY (").append(GlobalConstant.DEFAULT_PK).append(") \n");
sb.append(") \n");
sqls.add(sb.toString());
}
for (TableStructureConfig tableStructureConfig : tableStructureConfigs) {
List<TableFieldConfig> tableFieldConfigs = tableStructureConfig.getTableFieldConfigs();
//遍历当前表配置的 字段配置
for (TableFieldConfig tableFieldConfig : tableFieldConfigs) {
sqls.add("COMMENT ON COLUMN " + tableStructureConfig.getTableName() + "." + tableFieldConfig.getFieldName() + " IS '" + tableFieldConfig.getFieldComment() + "'");
}
}
return sqls;
}
private static List<String> wrapperCreateTableSqlForSqlServer(List<TableStructureConfig> tableStructureConfigs) {
List<String> sqls = new ArrayList<>();
//遍历所有表配置
for (TableStructureConfig tableStructureConfig : tableStructureConfigs) {
// 创建新表和覆盖旧表才需要创建表
Integer operator = tableStructureConfig.getOperator();
if (operator == 1) {
continue;
}
if (operator == 3) {
sqls.add(wrapperDropSql(tableStructureConfig.getTableName()));
}
StringBuilder sb = new StringBuilder();
sb.append("CREATE TABLE ").append(tableStructureConfig.getTableName()).append(" ( \n");
sb.append(" ").append(GlobalConstant.DEFAULT_PK).append(" bigint NOT NULL, \n");
List<TableFieldConfig> tableFieldConfigs = tableStructureConfig.getTableFieldConfigs();
//遍历当前表配置的 字段配置
for (TableFieldConfig tableFieldConfig : tableFieldConfigs) {
SqlServerFieldsType fieldType = SqlServerFieldsType.getFieldType(tableFieldConfig.getFieldType());
String type = fieldType.getType();
switch (fieldType) {
//普通文本
case VARCHAR:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(").append(tableFieldConfig.getFieldLength()).append("), \n");
break;
//长文本
case VARCHARMAX:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(max), \n");
break;
//数字
case INT:
//小数
case FLOAT:
//日期
case DATE:
case DATETIME:
//长数字
case LONG:
// 时间
case TIME:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append(", \n");
break;
default:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(").append(GlobalConstant.DEFAULT_TEXT_LENGTH).append("), \n");
break;
}
}
//如果不是主表 默认需要新增主表关联字段 用于关联主表 默认字段名为 parent + _id
if(!tableStructureConfig.getIsMain()){
sb.append(" ").append(GlobalConstant.DEFAULT_FK).append(" bigint , \n");
}
if (BooleanUtils.isTrue(tenantConfig.getEnabled())) {
sb.append(" ").append(tenantConfig.getTenantField()).append(" bigint , \n");
}
sb.append(" PRIMARY KEY (").append(GlobalConstant.DEFAULT_PK).append(") \n");
sb.append("); \n");
sqls.add(sb.toString());
}
return sqls;
}
private static List<String> wrapperCreateTableSqlForPostgreSql(List<TableStructureConfig> tableStructureConfigs) {
List<String> sqls = new ArrayList<>();
//遍历所有表配置
for (TableStructureConfig tableStructureConfig : tableStructureConfigs) {
// 创建新表和覆盖旧表才需要创建表
Integer operator = tableStructureConfig.getOperator();
if (operator == 1) {
continue;
}
if (operator == 3) {
sqls.add(wrapperDropSql(tableStructureConfig.getTableName()));
}
StringBuilder sb = new StringBuilder();
sb.append("CREATE TABLE ").append(tableStructureConfig.getTableName()).append(" ( \n");
sb.append(" ").append(GlobalConstant.DEFAULT_PK).append(" bigint NOT NULL, \n");
List<TableFieldConfig> tableFieldConfigs = tableStructureConfig.getTableFieldConfigs();
//遍历当前表配置的 字段配置
for (TableFieldConfig tableFieldConfig : tableFieldConfigs) {
PostgreSqlFieldsType fieldType = PostgreSqlFieldsType.getFieldType(tableFieldConfig.getFieldType());
String type = fieldType.getType();
switch (fieldType) {
//普通文本
case VARCHAR:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(").append(tableFieldConfig.getFieldLength()).append("), \n");
break;
//长文本
case VARCHARMAX:
//数字
case INT:
//长数字
case LONG:
//小数
case FLOAT:
//日期
case DATE:
case DATETIME:
case TIME:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append(", \n");
break;
default:
sb.append(tableFieldConfig.getFieldName()).append(" ").append(type).append("(").append(GlobalConstant.DEFAULT_TEXT_LENGTH).append("), \n");
break;
}
}
//如果不是主表 默认需要新增主表关联字段 用于关联主表 默认字段名为 parent + _id
if(!tableStructureConfig.getIsMain()){
sb.append(" ").append(GlobalConstant.DEFAULT_FK).append(" ").append(PostgreSqlFieldsType.FK.getType()).append(" , \n");
}
if (BooleanUtils.isTrue(tenantConfig.getEnabled())) {
sb.append(" `").append(tenantConfig.getTenantField()).append(PostgreSqlFieldsType.FK.getType()).append(", \n");
}
sb.append(" PRIMARY KEY (").append(GlobalConstant.DEFAULT_PK).append(") \n");
sb.append("); \n");
sqls.add(sb.toString());
}
for (TableStructureConfig tableStructureConfig : tableStructureConfigs) {
List<TableFieldConfig> tableFieldConfigs = tableStructureConfig.getTableFieldConfigs();
//遍历当前表配置的 字段配置
for (TableFieldConfig tableFieldConfig : tableFieldConfigs) {
sqls.add("COMMENT ON COLUMN " + tableStructureConfig.getTableName() + "." + tableFieldConfig.getFieldName() + " IS '" + tableFieldConfig.getFieldComment() + "'");
}
}
return sqls;
}
/**
* 构建 判断表是否存在的sql
* @param tableName
* @param dbType
* @return
*/
private static String wrapperExistTableSql(String tableName, DbType dbType) {
switch (dbType) {
case ORACLE:
case ORACLE_12C:
return wrapperExistTableSqlForOracle(tableName);
case SQL_SERVER:
return wrapperExistTableSqlForSqlServer(tableName);
case POSTGRE_SQL:
return wrapperExistTableSqlForPostgreSql(tableName);
case DM:
return wrapperExistTableSqlForDm(tableName);
case DB2:
return wrapperExistTableSqlForDb2(tableName);
case KINGBASE_ES:
return wrapperExistTableSqlForKingBaseEs(tableName);
case GAUSS:
return wrapperExistTableSqlForGauss(tableName);
default:
return wrapperExistTableSqlForMysql(tableName);
}
}
private static String wrapperExistTableSqlForMysql(String tableName) {
return "select count(*) from information_schema.TABLES where TABLE_NAME = '" + tableName + "'";
}
private static String wrapperExistTableSqlForOracle(String tableName) {
return "select count(*) from user_tables where table_name = '" + tableName + "'";
}
private static String wrapperExistTableSqlForSqlServer(String tableName) {
return "select count(*) from sys.objects where object_id = OBJECT_ID('" + tableName + "')";
}
private static String wrapperExistTableSqlForPostgreSql(String tableName) {
return "select count(*) from pg_catalog.pg_tables where tablename = '" + tableName + "'";
}
private static String wrapperExistTableSqlForDm(String tableName) {
return "select count(*) from sysobjects where NAME = '" + tableName + "'";
}
private static String wrapperExistTableSqlForDb2(String tableName) {
return "select count(*) from sysibm.systables where tablename = '" + tableName + "'";
}
private static String wrapperExistTableSqlForKingBaseEs(String tableName) {
return "select count(*) from sys_tables where table_name = '" + tableName + "'";
}
private static String wrapperExistTableSqlForGauss(String tableName) {
return "select count(*) from sys_tables where table_name = '" + tableName + "'";
}
public static Boolean testConnection(String url, String userName, String password) {
try (SimpleDataSource ds = new SimpleDataSource(url, userName, password)) {
DbUtil.use(ds).query(wrapperTestSql(JdbcUtils.getDbType(url)));
} catch (Exception e) {
log.error("数据库连接失败url: " + url, e);
return false;
}
return true;
}
public static String getDbType(DbType dbType, Integer typeCode) {
switch (dbType) {
case ORACLE:
case ORACLE_12C:
case DM:
case DB2:
return OracleFieldsType.getFieldType(typeCode).getType();
case SQL_SERVER:
return SqlServerFieldsType.getFieldType(typeCode).getType();
case POSTGRE_SQL:
case KINGBASE_ES:
case GAUSS:
return PostgreSqlFieldsType.getFieldType(typeCode).getType();
default:
return MySqlFieldsType.getFieldType(typeCode).getType();
}
}
public static DbType getDbType(String datasourceId) {
DataSource dataSource = getDataSource(datasourceId);
if (dataSource != null) {
Connection connection = null;
try {
connection = dataSource.getConnection();
return JdbcUtils.getDbType(connection.getMetaData().getURL());
} catch (Exception e) {
log.error("获取数据库类型失败!", e);
} finally {
DbUtil.close(connection);
}
}
return null;
}
}

View File

@ -0,0 +1,164 @@
package com.xjrsoft.common.mybatis.utils;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import oracle.sql.INTERVALDS;
import org.apache.commons.lang3.StringUtils;
import java.time.*;
import java.time.format.DateTimeFormatter;
public final class LocalDateTimeUtil {
private LocalDateTimeUtil(){}
public final static String LOCAL_TIME_FORMAT = "HH:mm:ss";
public final static String LOCAL_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public final static String LOCAL_DATE_FORMAT = "yyyy-MM-dd";
public final static String YEAR_MONTH_FORMAT = "yyyy-MM";
public final static String YEAR_FORMAT = "yyyy";
public static LocalTime parseTime(String value) {
return parseTime(value, LOCAL_TIME_FORMAT);
}
public static LocalTime parseTime(String value, String format) {
if (StrUtil.isBlank(value)) {
return null;
}
return LocalTime.parse(value, DateTimeFormatter.ofPattern(format));
}
public static LocalDateTime parseDate(String value) {
return parseDate(value, LOCAL_DATE_TIME_FORMAT);
}
public static LocalDateTime parseDate(String value, String format) {
if (StrUtil.isBlank(value)) {
return null;
}
// 根据format切掉多余的时间
value = StringUtils.substring(value, 0, format.length());
LocalDateTime localDateTime = null;
format = convertFontFormat(format);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
switch (format) {
case YEAR_FORMAT:
Year year = Year.parse(value, dateTimeFormatter);
localDateTime = LocalDateTime.from(year.atDay(1).atStartOfDay());
break;
case YEAR_MONTH_FORMAT:
YearMonth yearMonth = YearMonth.parse(value, dateTimeFormatter);
localDateTime = LocalDateTime.from(yearMonth.atDay(1).atStartOfDay());
break;
case LOCAL_DATE_FORMAT:
LocalDate localDate = LocalDate.parse(value, dateTimeFormatter);
localDateTime = LocalDateTime.from(localDate.atStartOfDay());
break;
default:
localDateTime = LocalDateTime.parse(value, dateTimeFormatter);
break;
}
return localDateTime;
}
public static String convertFontFormat(String fontFormat) {
if (StrUtil.isEmpty(fontFormat)) {
return fontFormat;
}
return fontFormat.replace("YYYY", "yyyy").replace("DD", "dd");
}
public static String format(LocalDateTime dateTime, String format) {
if (dateTime == null) {
return StringPool.EMPTY;
}
return dateTime.format(DateTimeFormatter.ofPattern(format));
}
public static String format(LocalTime time) {
if (time == null) {
return StringPool.EMPTY;
}
return time.format(DateTimeFormatter.ofPattern(LOCAL_TIME_FORMAT));
}
/**
* 将时间字符串转换成数据库对应的时间类型
* @param time 时间字符串 格式 HH:mm:ss
* @param dbType 数据库类型
* @return 据库对应的时间类型对象
*/
public static Object parseDbTime(String time, DbType dbType) {
if (dbType == DbType.ORACLE || dbType == DbType.ORACLE_12C) {
return new INTERVALDS("0 " + time + ".0");
} else {
return parseTime(time);
}
}
public static LocalDateTime parseDateByLength(String value) {
if (StrUtil.isNotBlank(value)) {
value = value.trim();
int length = value.length();
if (LOCAL_DATE_FORMAT.length() == length) {
LocalDate localDate = LocalDate.parse(value, DateTimeFormatter.ofPattern(LOCAL_DATE_FORMAT));
return LocalDateTime.from(localDate.atStartOfDay());
} else if (LOCAL_DATE_TIME_FORMAT.length() == length) {
return LocalDateTime.parse(value, DateTimeFormatter.ofPattern(LOCAL_DATE_TIME_FORMAT));
} else if (YEAR_MONTH_FORMAT.length() == length) {
YearMonth yearMonth = YearMonth.parse(value, DateTimeFormatter.ofPattern(YEAR_MONTH_FORMAT));
return LocalDateTime.from(yearMonth.atDay(1).atStartOfDay());
} else if (YEAR_FORMAT.length() == length) {
Year year = Year.parse(value, DateTimeFormatter.ofPattern(YEAR_FORMAT));
return LocalDateTime.from(year.atDay(1).atStartOfDay());
}
}
return null;
}
public static LocalTime convertIntervalToLocalTime(INTERVALDS intervalDS) {
if (intervalDS == null) {
return null;
}
String str = intervalDS.stringValue();
String timeStr = str.substring(str.indexOf(StringPool.SPACE) + 1, str.indexOf(StringPool.DOT));
String[] array = timeStr.split(StringPool.COLON);
return LocalTime.of(Integer.parseInt(array[0]), Integer.parseInt(array[1]), Integer.parseInt(array[2]));
}
public static String tranDurationToShow(Duration duration) {
StringBuilder result = new StringBuilder();
long days = duration.toDays();
if (days >= 1) {
result.append(days).append("");
}
long hours = duration.toHours();
if (hours >= 1) {
if (days >= 1) {
long l = hours % 24;
if (l > 0) result.append(l).append("小时");
return result.toString();
}
result.append(hours).append("小时");
}
long minutes = duration.toMinutes();
if (minutes >= 1) {
if (hours >= 1) {
long l = minutes % 60;
if (l > 0) result.append(l).append("分钟");
return result.toString();
}
result.append(minutes).append("分钟");
}
if (result.length() == 0) {
result.append("1分钟内");
}
return result.toString();
}
}

View File

@ -0,0 +1,30 @@
package com.xjrsoft.common.mybatis.utils;
import cn.hutool.db.Entity;
import cn.hutool.db.Page;
import cn.hutool.db.PageResult;
import cn.hutool.db.SqlConnRunner;
import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.sql.SqlBuilder;
import com.xjrsoft.common.mybatis.handler.XjrPageResultHandler;
import java.sql.Connection;
import java.sql.SQLException;
public class XjrSqlConnRunner extends SqlConnRunner {
public XjrSqlConnRunner(Dialect dialect) {
super(dialect);
}
public XjrSqlConnRunner(String driverClassName) {
super(driverClassName);
}
@Override
public PageResult<Entity> page(Connection conn, SqlBuilder sqlBuilder, Page page) throws SQLException {
final XjrPageResultHandler pageResultHandler = new XjrPageResultHandler(
new PageResult<>(page.getPageNumber(), page.getPageSize(), (int) count(conn, sqlBuilder)),
this.caseInsensitive);
return page(conn, sqlBuilder, page, pageResultHandler);
}
}

View File

@ -0,0 +1 @@
com.xjrsoft.common.mybatis.MybatisplusAutoConfiguration