From 54f248733022438d1587871f89da547e3c335e8a Mon Sep 17 00:00:00 2001 From: gx_ma <1773945958@qq.com> Date: Tue, 22 Apr 2025 10:03:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=A4=9A=E6=95=B0=E6=8D=AE=E6=BA=90?= =?UTF-8?q?=E8=84=9A=E6=9C=AC):=20=E8=BE=BE=E6=A2=A6=E3=80=81SQL=20server?= =?UTF-8?q?=E3=80=81postgres?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/fastbee/FastBeeApplication.java | 2 +- .../common/mabatis/enums/DataBaseType.java | 64 + springboot/fastbee-framework/pom.xml | 7 + .../framework/config/DataSourceConfig.java | 69 + .../mybatis/helper/DataBaseHelper.java | 164 + .../fastbee/data/service/impl/DeviceJob.java | 4 +- .../fastbee/sip/mapper/SipDeviceMapper.java | 2 +- .../main/resources/mapper/SipDeviceMapper.xml | 2 +- .../fastbee-iot-service/pom.xml | 7 + .../fastbee-system-service/pom.xml | 6 + springboot/sql/dameng/fastbee-v2.1.sql | 3226 ++++++ springboot/sql/postgres/fastbee-v2.1.sql | 4434 ++++++++ springboot/sql/sqlserver/fastbee-v2.1.sql | 9327 +++++++++++++++++ 13 files changed, 17310 insertions(+), 4 deletions(-) create mode 100644 springboot/fastbee-common/src/main/java/com/fastbee/common/mabatis/enums/DataBaseType.java create mode 100644 springboot/fastbee-framework/src/main/java/com/fastbee/framework/config/DataSourceConfig.java create mode 100644 springboot/fastbee-framework/src/main/java/com/fastbee/framework/mybatis/helper/DataBaseHelper.java create mode 100644 springboot/sql/dameng/fastbee-v2.1.sql create mode 100644 springboot/sql/postgres/fastbee-v2.1.sql create mode 100644 springboot/sql/sqlserver/fastbee-v2.1.sql diff --git a/springboot/fastbee-admin/src/main/java/com/fastbee/FastBeeApplication.java b/springboot/fastbee-admin/src/main/java/com/fastbee/FastBeeApplication.java index 945d7de5..b9833640 100644 --- a/springboot/fastbee-admin/src/main/java/com/fastbee/FastBeeApplication.java +++ b/springboot/fastbee-admin/src/main/java/com/fastbee/FastBeeApplication.java @@ -9,7 +9,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; * * @author ruoyi */ -@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) +@SpringBootApplication public class FastBeeApplication { public static void main(String[] args) diff --git a/springboot/fastbee-common/src/main/java/com/fastbee/common/mabatis/enums/DataBaseType.java b/springboot/fastbee-common/src/main/java/com/fastbee/common/mabatis/enums/DataBaseType.java new file mode 100644 index 00000000..2fef9e70 --- /dev/null +++ b/springboot/fastbee-common/src/main/java/com/fastbee/common/mabatis/enums/DataBaseType.java @@ -0,0 +1,64 @@ +package com.fastbee.common.mabatis.enums; + +import com.fastbee.common.utils.StringUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; + + +/** + * 数据库类型 + * + * @author Lion Li + */ +@Getter +@AllArgsConstructor +public enum DataBaseType { + + /** + * MySQL + */ + MY_SQL("MySQL"), + + /** + * Oracle + */ + ORACLE("Oracle"), + + /** + * PostgreSQL + */ + POSTGRE_SQL("PostgreSQL"), + + /** + * SQL Server + */ + SQL_SERVER("Microsoft SQL Server"), + + /** + * 达梦 + */ + DM("DM DBMS"); + + /** + * 数据库类型 + */ + private final String type; + + /** + * 根据数据库产品名称查找对应的数据库类型 + * + * @param databaseProductName 数据库产品名称 + * @return 对应的数据库类型枚举值,如果未找到则返回 null + */ + public static DataBaseType find(String databaseProductName) { + if (StringUtils.isBlank(databaseProductName)) { + return null; + } + for (DataBaseType type : values()) { + if (type.getType().equals(databaseProductName)) { + return type; + } + } + return null; + } +} diff --git a/springboot/fastbee-framework/pom.xml b/springboot/fastbee-framework/pom.xml index b628b4e8..91196f4a 100644 --- a/springboot/fastbee-framework/pom.xml +++ b/springboot/fastbee-framework/pom.xml @@ -59,6 +59,13 @@ oshi-core + + + com.baomidou + dynamic-datasource-spring-boot-starter + ${dynamic-datasource.version} + + diff --git a/springboot/fastbee-framework/src/main/java/com/fastbee/framework/config/DataSourceConfig.java b/springboot/fastbee-framework/src/main/java/com/fastbee/framework/config/DataSourceConfig.java new file mode 100644 index 00000000..92fd89af --- /dev/null +++ b/springboot/fastbee-framework/src/main/java/com/fastbee/framework/config/DataSourceConfig.java @@ -0,0 +1,69 @@ +package com.fastbee.framework.config; + +import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; +import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator; +import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider; +import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@Configuration +public class DataSourceConfig { + private final DynamicDataSourceProperties properties; + private final DefaultDataSourceCreator dataSourceCreator; + private final DataSource shardingSphereDataSource; + + public DataSourceConfig(DynamicDataSourceProperties properties, + DefaultDataSourceCreator dataSourceCreator, + @Lazy + @Qualifier("shardingSphereDataSource") DataSource shardingSphereDataSource) { + this.properties = properties; + this.dataSourceCreator = dataSourceCreator; + this.shardingSphereDataSource = shardingSphereDataSource; + } + + + @Bean + public DynamicDataSourceProvider dynamicDataSourceProvider() { + return new AbstractDataSourceProvider(dataSourceCreator) { + @Override + public Map loadDataSources() { + Map dataSourceMap = new HashMap<>(); + // 把 shardingSphereDataSource 加入多数据源,到时候使用的时候就可以 `@DS("shardingSphere")` + if(null != shardingSphereDataSource) { + dataSourceMap.put("shardingSphere", shardingSphereDataSource); + } + return dataSourceMap; + } + }; + } + + @Primary + @Bean + public DataSource dataSource(List providers) { + DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource(providers); + dataSource.setPrimary(properties.getPrimary()); + dataSource.setStrict(properties.getStrict()); + dataSource.setStrategy(properties.getStrategy()); + dataSource.setP6spy(properties.getP6spy()); + dataSource.setSeata(properties.getSeata()); + return dataSource; + } + + + @Bean + public DataSourceTransactionManager transactionManager(DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } +} diff --git a/springboot/fastbee-framework/src/main/java/com/fastbee/framework/mybatis/helper/DataBaseHelper.java b/springboot/fastbee-framework/src/main/java/com/fastbee/framework/mybatis/helper/DataBaseHelper.java new file mode 100644 index 00000000..2299365c --- /dev/null +++ b/springboot/fastbee-framework/src/main/java/com/fastbee/framework/mybatis/helper/DataBaseHelper.java @@ -0,0 +1,164 @@ +package com.fastbee.framework.mybatis.helper; + +import cn.hutool.core.convert.Convert; +import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; +import com.fastbee.common.exception.ServiceException; +import com.fastbee.common.mabatis.enums.DataBaseType; +import com.fastbee.common.utils.spring.SpringUtils; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * 数据库助手 + * + * @author Lion Li + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class DataBaseHelper { + + private static final DynamicRoutingDataSource DS = SpringUtils.getBean(DynamicRoutingDataSource.class); + public static final String DEFAULT_DATASOURCE_NAME = "master"; + + /** + * 获取当前数据库类型 + */ + public static DataBaseType getDataBaseType(String dataName) { + DataSource dataSource = DS.getDataSources().get(dataName); + try (Connection conn = dataSource.getConnection()) { + DatabaseMetaData metaData = conn.getMetaData(); + String databaseProductName = metaData.getDatabaseProductName(); + return DataBaseType.find(databaseProductName); + } catch (SQLException e) { + throw new ServiceException(e.getMessage()); + } + } + + public static boolean isMySql() { + return DataBaseType.MY_SQL == getDataBaseType(DEFAULT_DATASOURCE_NAME); + } + + public static boolean isOracle() { + return DataBaseType.ORACLE == getDataBaseType(DEFAULT_DATASOURCE_NAME); + } + + public static boolean isPostgerSql() { + return DataBaseType.POSTGRE_SQL == getDataBaseType(DEFAULT_DATASOURCE_NAME); + } + + public static boolean isSqlServer() { + return DataBaseType.SQL_SERVER == getDataBaseType(DEFAULT_DATASOURCE_NAME); + } + + public static boolean isDm() { + return DataBaseType.DM == getDataBaseType(DEFAULT_DATASOURCE_NAME); + } + + public static boolean isMySql(String dataName) { + return DataBaseType.MY_SQL == getDataBaseType(dataName); + } + + public static boolean isOracle(String dataName) { + return DataBaseType.ORACLE == getDataBaseType(dataName); + } + + public static boolean isPostgerSql(String dataName) { + return DataBaseType.POSTGRE_SQL == getDataBaseType(dataName); + } + + public static boolean isSqlServer(String dataName) { + return DataBaseType.SQL_SERVER == getDataBaseType(dataName); + } + + public static boolean isDm(String dataName) { + return DataBaseType.DM == getDataBaseType(dataName); + } + + public static String findInSet(Object var1, String var2) { + DataBaseType dataBasyType = getDataBaseType(DEFAULT_DATASOURCE_NAME); + String var = Convert.toStr(var1); + if (dataBasyType == DataBaseType.SQL_SERVER) { + // charindex(',100,' , ',0,100,101,') <> 0 + return String.format("charindex(',%s,' , ','+%s+',') <> 0", var, var2); + } else if (dataBasyType == DataBaseType.POSTGRE_SQL) { + // (select strpos(',0,100,101,' , ',100,')) <> 0 + return String.format("(select strpos(','||%s||',' , ',%s,')) <> 0", var2, var); + } else if (dataBasyType == DataBaseType.ORACLE || dataBasyType == DataBaseType.DM) { + // instr(',0,100,101,' , ',100,') <> 0 + return String.format("instr(','||%s||',' , ',%s,') <> 0", var2, var); + } + // find_in_set(100 , '0,100,101') + return String.format("find_in_set(%s , %s) <> 0", var, var2); + } + + public static String findInSetColumn(String var1, String var2) { + DataBaseType dataBasyType = getDataBaseType(DEFAULT_DATASOURCE_NAME); + String var = Convert.toStr(var1); + if (dataBasyType == DataBaseType.SQL_SERVER) { + // charindex(','+de.dept_id+',' , ',0,100,101,') <> 0 + return String.format("charindex(',' + %s + ',' , ',' + %s + ',') <> 0", var, var2); + } else if (dataBasyType == DataBaseType.POSTGRE_SQL) { + // (select strpos(',0,100,101,' , ',' || de.dept_id || ',')) <> 0 + return String.format("(select strpos(','||%s||',' , ','|| %s ||',')) <> 0", var2, var); + } else if (dataBasyType == DataBaseType.ORACLE|| dataBasyType == DataBaseType.DM) { + // instr(',0,100,101,' , ','||de.dept_id||',') <> 0 + return String.format("instr(','||%s||',' , ','||%s||',') <> 0", var2, var); + } + // find_in_set(de.dept_id , '0,100,101') + return String.format("find_in_set(%s , '%s') <> 0", var, var2); + } + + /** + * 获取当前加载的数据库名 + */ + public static List getDataSourceNameList() { + return new ArrayList<>(DS.getDataSources().keySet()); + } + + public static String getDeptCondition(Long deptId) { + if (deptId == null || deptId == 0) { + // 无效条件,确保查询不会返回结果 + return "1=1"; + } + if (isPostgerSql()) { + return "SELECT u.user_id FROM sys_user u WHERE u.dept_id IN (SELECT dept_id FROM sys_dept WHERE " + deptId + "::text = ANY(string_to_array(ancestors, ',')) OR dept_id = " + deptId + ")"; + } else if (isSqlServer()) { + return "SELECT u.user_id FROM sys_user u WHERE u.dept_id IN (SELECT dept_id FROM sys_dept WHERE CHARINDEX(',' + CAST(" + deptId + " AS VARCHAR) + ',', ',' + ancestors + ',') > 0 OR dept_id = " + deptId + ")"; + } else if (isOracle()) { + return "SELECT u.user_id FROM sys_user u WHERE u.dept_id IN (SELECT dept_id FROM sys_dept WHERE INSTR(',' || ancestors || ',', ',' || " + deptId + " || ',') > 0 OR dept_id = " + deptId + ")"; + } else if (isDm()) { + return "SELECT u.user_id FROM sys_user u WHERE u.dept_id IN (SELECT dept_id FROM sys_dept WHERE INSTR(',' || ancestors || ',', ',' || " + deptId + " || ',') > 0 OR dept_id = " + deptId + ")"; + } else if (isMySql()) { + return "SELECT u.user_id FROM sys_user u WHERE u.dept_id IN (SELECT dept_id FROM sys_dept WHERE FIND_IN_SET(" + deptId + ", ancestors) > 0 OR dept_id = " + deptId + ")"; + } else { + throw new UnsupportedOperationException("Unsupported database type"); + } + } + + public static String checkTime(Integer timeout) { + if (timeout == null || timeout == 0) { + // 无效条件,确保查询不会返回结果 + return ""; + } + if (isPostgerSql()) { + return "CURRENT_TIMESTAMP > last_connect_time + interval '1 seconds' * " + timeout; + } else if (isSqlServer()) { + return "CURRENT_TIMESTAMP > DATEADD(SECOND, " + timeout + " last_connect_time)"; + } else if (isOracle()) { + return "CURRENT_TIMESTAMP > last_connect_time + (" + timeout + " / 86400)"; + } else if (isDm()) { + return "CURRENT_TIMESTAMP > DATEADD(SECOND, " + timeout + ", last_connect_time)"; + } else if (isMySql()) { + return "CURRENT_TIMESTAMP > DATE_ADD(last_connect_time, INTERVAL " + timeout + " SECOND)"; + } else { + throw new UnsupportedOperationException("Unsupported database type"); + } + } + +} diff --git a/springboot/fastbee-open-api/src/main/java/com/fastbee/data/service/impl/DeviceJob.java b/springboot/fastbee-open-api/src/main/java/com/fastbee/data/service/impl/DeviceJob.java index 8ae40e5f..7497f5ef 100644 --- a/springboot/fastbee-open-api/src/main/java/com/fastbee/data/service/impl/DeviceJob.java +++ b/springboot/fastbee-open-api/src/main/java/com/fastbee/data/service/impl/DeviceJob.java @@ -2,6 +2,7 @@ package com.fastbee.data.service.impl; import com.fastbee.base.session.Session; import com.fastbee.common.enums.DeviceStatus; +import com.fastbee.framework.mybatis.helper.DataBaseHelper; import com.fastbee.iot.domain.Device; import com.fastbee.iot.model.DeviceStatusVO; import com.fastbee.iot.service.IDeviceService; @@ -42,7 +43,8 @@ public class DeviceJob { private Boolean enabled; public void updateSipDeviceOnlineStatus(Integer timeout) { - List devs = sipDeviceMapper.selectOfflineSipDevice(timeout); + String checkTimeCondition = DataBaseHelper.checkTime(timeout); + List devs = sipDeviceMapper.selectOfflineSipDevice(checkTimeCondition); devs.forEach(item -> { if (!Objects.equals(item.getDeviceSipId(), "")) { //更新iot设备状态 diff --git a/springboot/fastbee-server/sip-server/src/main/java/com/fastbee/sip/mapper/SipDeviceMapper.java b/springboot/fastbee-server/sip-server/src/main/java/com/fastbee/sip/mapper/SipDeviceMapper.java index d84875f3..8a79b384 100644 --- a/springboot/fastbee-server/sip-server/src/main/java/com/fastbee/sip/mapper/SipDeviceMapper.java +++ b/springboot/fastbee-server/sip-server/src/main/java/com/fastbee/sip/mapper/SipDeviceMapper.java @@ -31,7 +31,7 @@ public interface SipDeviceMapper * @return 监控设备集合 */ public List selectSipDeviceList(SipDevice sipDevice); - public List selectOfflineSipDevice(Integer timeout); + public List selectOfflineSipDevice(String checkTimeCondition); /** * 新增监控设备 diff --git a/springboot/fastbee-server/sip-server/src/main/resources/mapper/SipDeviceMapper.xml b/springboot/fastbee-server/sip-server/src/main/resources/mapper/SipDeviceMapper.xml index 73237e0c..208f1d13 100644 --- a/springboot/fastbee-server/sip-server/src/main/resources/mapper/SipDeviceMapper.xml +++ b/springboot/fastbee-server/sip-server/src/main/resources/mapper/SipDeviceMapper.xml @@ -196,7 +196,7 @@