动态新增数据源成功

dev
1iyc 1 week ago
parent 58a14e31c2
commit 4bd634fa63

@ -216,11 +216,12 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<parameters>true</parameters>
</configuration>
</plugin>
</plugins>

@ -1,11 +1,7 @@
package com.lyr.web.controller.tool;
import com.lyr.framework.manager.DataSourceManagerService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author liyc
* @date 2024/10/30

@ -16,8 +16,18 @@ import java.lang.annotation.*;
@Documented
@Inherited
public @interface DataSource {
/**
*
*/
DataSourceType value() default DataSourceType.MASTER;
/**
* (使,使value)
*
* @return
*/
String name() default "";
}

@ -14,5 +14,11 @@ public enum DataSourceType {
/**
*
*/
SLAVE
SLAVE,
/**
*
*/
EXTERNAL
}

@ -0,0 +1,104 @@
package com.lyr.common.utils;
import com.lyr.common.exception.ServiceException;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.List;
/**
* @author Admin
*/
public class AssertUtil {
public static void notEmpty(Long val, String s, Integer... codes) throws ServiceException {
if (val == null) {
Integer code = (codes.length == 0) ? 500 : codes[0];
throw new ServiceException(s, code);
}
}
public static void notEmpty(Collection c, String s, Integer... codes) throws ServiceException {
if (CollectionUtils.isEmpty(c)) {
Integer code = (codes.length == 0) ? 500 : codes[0];
throw new ServiceException(s, code);
}
}
public static void notEmpty(String val, String s, Integer... codes) throws ServiceException {
if (StringUtils.isEmpty(val)) {
Integer code = (codes.length == 0) ? 500 : codes[0];
throw new ServiceException(s, code);
}
}
public static void notEmpty(Object val, String s, Integer... codes) throws ServiceException {
if (val == null) {
Integer code = (codes.length == 0) ? 500 : codes[0];
throw new ServiceException(s, code);
}
}
/**
*
*
* @param obj
* @param s
*/
public static void empty(Object obj, String s, Integer... codes) {
if (null != obj) {
Integer code = (codes.length == 0) ? 500 : codes[0];
throw new ServiceException(s, code);
}
}
public static void empty(Object obj, String s, List<T> t, Integer... codes) {
if (null != obj) {
Integer code = (codes.length == 0) ? 500 : codes[0];
throw new ServiceException(s, code);
}
}
public static void empty(Collection c, String s) {
if (!CollectionUtils.isEmpty(c)) {
throw new ServiceException(s, 500);
}
}
public static void notEqual(boolean val, String s, Integer... codes) {
if (val) {
Integer code = (codes.length == 0) ? 500 : codes[0];
throw new ServiceException(s, code);
}
}
public static void equal(boolean val, String s) {
notEqual(!val, s);
}
public static void isFalse(boolean b, String s, Integer... codes) {
if (b) {
Integer code = (codes.length == 0) ? 500 : codes[0];
throw new ServiceException(s, code);
}
}
public static void isTrue(boolean b, String s, Integer... codes) throws ServiceException {
if (!b) {
Integer code = (codes.length == 0) ? 500 : codes[0];
throw new ServiceException(s, code);
}
}
public static void test() {
throw new ServiceException("222");
}
}

@ -0,0 +1,49 @@
package com.lyr.common.utils;
import org.springframework.context.annotation.Bean;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
/**
* spel
*
* @author liyc
* @date 2024/10/30
* @description TODO
**/
@Component
public class SpElUtil {
@Resource
public ExpressionParser expressionParser;
@Bean
public ExpressionParser expressionParser() {
return new SpelExpressionParser();
}
/**
*
*
* @param method
* @param args
* @param expression
* @return
*/
public String parseExpression(Method method, Object[] args, String expression) {
StandardEvaluationContext context = new StandardEvaluationContext();
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
context.setVariable(parameter.getName(), args[i]);
}
return expressionParser.parseExpression(expression).getValue(context, String.class);
}
}

@ -74,6 +74,11 @@
<groupId>com.lyr</groupId>
<artifactId>sync-system</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

@ -1,8 +1,11 @@
package com.lyr.framework.aspectj;
import com.lyr.common.annotation.DataSource;
import com.lyr.common.exception.ServiceException;
import com.lyr.common.utils.SpElUtil;
import com.lyr.common.utils.StringUtils;
import com.lyr.framework.datasource.DynamicDataSourceContextHolder;
import com.lyr.framework.manager.DataSourceManager;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@ -14,6 +17,8 @@ import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Objects;
/**
@ -27,28 +32,46 @@ import java.util.Objects;
public class DataSourceAspect {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Pointcut("@annotation(com.lyr.common.annotation.DataSource)"
+ "|| @within(com.lyr.common.annotation.DataSource)")
@Resource
private SpElUtil spElUtil;
@Resource
private DataSourceManager dataSourceManager;
@Pointcut("@annotation(com.lyr.common.annotation.DataSource)" + "|| @within(com.lyr.common.annotation.DataSource)")
public void dsPointCut() {
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
String value = null;
DataSource dataSource = getDataSource(point);
if (StringUtils.isNotNull(dataSource)) {
DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
value = dataSource.value().name();
String name = dataSource.name();
if (StringUtils.isNotEmpty(name)) {
// 解析spEl表达式
Object[] args = point.getArgs();
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
value = spElUtil.parseExpression(method, args, dataSource.name());
}
DynamicDataSourceContextHolder.setDataSourceType(value);
}
try {
return point.proceed();
} catch (Exception e) {
logger.error("数据源切换失败", e);
logger.debug("要切换的数据源:{}", value);
dataSourceManager.print();
throw new ServiceException("切换数据源到[" + value + "]失败");
} finally {
// 销毁数据源 在执行方法之后
DynamicDataSourceContextHolder.clearDataSourceType();
}
}
/**
*
*/
@ -58,7 +81,8 @@ public class DataSourceAspect {
if (Objects.nonNull(dataSource)) {
return dataSource;
}
return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
}
}

@ -1,10 +1,9 @@
package com.lyr.framework.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.lyr.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -13,6 +12,7 @@ import java.util.concurrent.ConcurrentHashMap;
*
* @author ruoyi
*/
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {
private static Map<Object, Object> targetDataSources = new ConcurrentHashMap<>();
@ -28,13 +28,14 @@ public class DynamicDataSource extends AbstractRoutingDataSource {
}
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
/**
*
*
* @param key
* @param dataSource
*/
public void addTargetDataSource(Object key, Object dataSource) {
try {
if (dataSource instanceof String) {
try {
SpringUtils.getBean(dataSource.toString());
@ -45,6 +46,10 @@ public class DynamicDataSource extends AbstractRoutingDataSource {
this.targetDataSources.put(key, dataSource);
}
super.afterPropertiesSet(); // 重新初始化数据源
} catch (Exception e) {
log.error("添加数据源失败", e);
throw new RuntimeException(e);
}
}
@ -53,13 +58,5 @@ public class DynamicDataSource extends AbstractRoutingDataSource {
super.afterPropertiesSet(); // 重新初始化数据源
}
public void print() {
DruidDataSource resolvedDefaultDataSource = (DruidDataSource) getResolvedDefaultDataSource();
System.out.println("主数据源:" + resolvedDefaultDataSource.getUrl());
Map<Object, DataSource> resolvedDataSources = getResolvedDataSources();
for (Map.Entry<Object, DataSource> entry : resolvedDataSources.entrySet()) {
DruidDataSource value = (DruidDataSource) entry.getValue();
System.out.println("数据源[" + entry.getKey() + "]:" + value.getUrl());
}
}
}

@ -9,6 +9,8 @@ import org.slf4j.LoggerFactory;
* @author ruoyi
*/
public class DynamicDataSourceContextHolder {
public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
/**

@ -0,0 +1,130 @@
package com.lyr.framework.manager;
import com.alibaba.druid.pool.DruidDataSource;
import com.lyr.common.exception.ServiceException;
import com.lyr.common.utils.AssertUtil;
import com.lyr.framework.datasource.DynamicDataSource;
import com.lyr.framework.datasource.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author liyc
* @date 2024/10/30
* @description TODO
**/
@Slf4j
@Component
public class DataSourceManager {
@Resource
private DynamicDataSource dynamicDataSource;
public enum RegisterType {
LOAD, ADD;
}
/**
*
*
* @param dataSource
* @param registerType
*/
public void defaultDataSourceConfiguration(DruidDataSource dataSource, RegisterType registerType) {
String dataSourceName = dataSource.getName();
AssertUtil.notEmpty(dataSourceName, "数据源名称不能为空");
// 配置数据源参数
dataSource.setInitialSize(5);
dataSource.setMinIdle(10);
dataSource.setMaxActive(20);
dataSource.setMaxWait(60000);
dataSource.setConnectTimeout(30000);
dataSource.setSocketTimeout(60000);
dataSource.setTimeBetweenEvictionRunsMillis(60000);
dataSource.setMinEvictableIdleTimeMillis(300000);
dataSource.setMaxEvictableIdleTimeMillis(900000);
dataSource.setValidationQuery("SELECT 1");
dataSource.setTestOnBorrow(false);
try {
DataSource resolvedDefaultDataSource = dynamicDataSource.getResolvedDefaultDataSource();
// 设置默认数据源
dynamicDataSource.setDefaultTargetDataSource(resolvedDefaultDataSource);
// 添加数据源
dynamicDataSource.addTargetDataSource(dataSourceName, dataSource);
// 测试数据源连接
this.testDataSourceConnection(dataSource, registerType);
} catch (ServiceException e) {
dataSource.close();
throw new ServiceException(e.getMessage());
} catch (Exception ex) {
String name = registerType.name();
String message = String.format("【%s】数据源配置失败", name);
log.error(message, ex);
dataSource.close();
throw new ServiceException(message);
}
}
/**
*
*
* @param dataSource
* @param registerType
*/
private void testDataSourceConnection(DruidDataSource dataSource, RegisterType registerType) {
String dataSourceName = dataSource.getName();
int compareTo = RegisterType.LOAD.compareTo(registerType);
String message = String.format("数据源连接测试未通过 %s",
(compareTo == 0 ? "排查表参数: data_source_config" : "请手动测试数据源是否正确"));
try (Connection connection = dataSource.getConnection()) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
Integer result = jdbcTemplate.queryForObject("SELECT 1", Integer.class);
if (result != null && result == 1) {
log.info(String.format("数据源连接测试通过", dataSourceName));
} else {
log.error(message);
throw new ServiceException(message);
}
} catch (SQLException e) {
log.error(message, e);
// 销毁数据源
DynamicDataSourceContextHolder.clearDataSourceType();
throw new ServiceException(message);
}
}
public void print() {
log.debug("=======================开始打印数据源信息=============================");
// 获取默认数据源
DruidDataSource resolvedDefaultDataSource = (DruidDataSource) dynamicDataSource.getResolvedDefaultDataSource();
if (resolvedDefaultDataSource != null) {
log.debug("主数据源: {}", resolvedDefaultDataSource.getUrl());
} else {
log.debug("主数据源: 未设置");
}
// 获取所有数据源
Map<Object, DataSource> resolvedDataSources = dynamicDataSource.getResolvedDataSources();
AtomicInteger index = new AtomicInteger(0);
for (Map.Entry<Object, DataSource> entry : resolvedDataSources.entrySet()) {
DruidDataSource value = (DruidDataSource) entry.getValue();
log.debug("数据源[{}]: {} {}", index.getAndIncrement(), entry.getKey(), value.getUrl());
}
log.debug("=======================打印数据源信息结束=============================");
}
}

@ -1,57 +0,0 @@
package com.lyr.framework.manager;
import com.lyr.framework.datasource.DynamicDataSource;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.sql.DataSource;
/**
* @author liyc
* @date 2024/10/30
* @description TODO
**/
@Component
public class DataSourceManagerService implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Resource
private DynamicDataSource dynamicDataSource;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void print() {
dynamicDataSource.print();
}
public void registerDataSources(String beanName, DataSource dataSource) {
DataSource resolvedDefaultDataSource = dynamicDataSource.getResolvedDefaultDataSource();
dynamicDataSource.setDefaultTargetDataSource(resolvedDefaultDataSource);
dynamicDataSource.addTargetDataSource(beanName, dataSource);
}
public void add() {
/* // 构建数据源
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:sqlserver://192.168.3.28:1433;DatabaseName=BiDataDeYue;encrypt=true;trustServerCertificate=true;");
dataSource.setUsername("sa");
dataSource.setPassword("mssql_whdZeB");
dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
try {
DataSource resolvedDefaultDataSource = dynamicDataSource.getResolvedDefaultDataSource();
dynamicDataSource.setDefaultTargetDataSource(resolvedDefaultDataSource);
dynamicDataSource.addTargetDataSource("deYueMssql", dataSource);
} catch (BeansException e) {
}*/
}
}

@ -13,7 +13,6 @@ import com.lyr.common.utils.MessageUtils;
import com.lyr.common.utils.StringUtils;
import com.lyr.common.utils.ip.IpUtils;
import com.lyr.framework.manager.AsyncManager;
import com.lyr.framework.manager.DataSourceManagerService;
import com.lyr.framework.manager.factory.AsyncFactory;
import com.lyr.framework.security.context.AuthenticationContextHolder;
import com.lyr.system.service.ISysConfigService;

@ -1,17 +1,21 @@
package com.lyr.gather.controller;
import com.lyr.gather.service.DataSourceConfigService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
/**
* @author liyc
* @date 2024/10/30
* @description TODO
**/
@Validated
@RestController
@RequestMapping("/gather")
public class DataSourceConfigController {
@ -31,4 +35,10 @@ public class DataSourceConfigController {
public void add() {
dataSourceConfigService.add();
}
@GetMapping("/list/{dataSource}")
public void list(@NotNull(message = "数据源名称不能为空") @PathVariable("dataSource") String datasourceName) {
dataSourceConfigService.list(datasourceName, null);
}
}

@ -1,4 +1,4 @@
package com.lyr.gather.domain.vo;
package com.lyr.gather.domain.model;
import com.lyr.common.annotation.Excel;
import lombok.Data;

@ -0,0 +1,108 @@
package com.lyr.gather.domain.model;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
@Data
@Accessors(chain = true)
public class TSupplier {
private Integer fItemId;
private String fAddress;
private String fCity;
private String fProvince;
private String fCountry;
private String fPostalCode;
private String fPhone;
private String fFax;
private String fEmail;
private String fHomePage;
private String fCreditLimit;
private String fTaxId;
private String fBank;
private String fAccount;
private String fBrNo;
private Integer fBoundAttr;
private Integer fErpClsId;
private String fShortName;
private Integer fPriorityId;
private Integer fPGroupId;
private Integer fStatus;
private Integer fLanguageId;
private Integer fRegionId;
private Integer fTrade;
private Double fMinPoValue;
private Double fMaxDebitDate;
private String fLegalPerson;
private String fContact;
private String fContactAcct;
private String fPhoneAcct;
private String fFaxAcct;
private String fZipAcct;
private String fEmailAcct;
private String fAddrAcct;
private Float fTax;
private Integer fCyId;
private Integer fSetId;
private Integer fSetDLineId;
private String fTaxNum;
private Integer fPriceClsId;
private Integer fOperId;
private String fCiqNumber;
private Short fDeleted;
private Short fSaleMode;
private String fName;
private String fNumber;
private Integer fParentId;
private String fShortNumber;
private Integer fArAccountId;
private Integer fApAccountId;
private Integer fPreAcctId;
private BigDecimal fLastTradeAmount;
private BigDecimal fLastRPAmount;
private String fFavorPolicy;
private Integer fDepartment;
private Integer fEmployee;
private String fCorperate;
private Date fBeginTradeDate;
private Date fEndTradeDate;
private Date fLastTradeDate;
private Date fLastReceiveDate;
private String fCashDiscount;
private Integer fCurrencyId;
private Double fMaxDealAmount;
private Double fMinForeReceiveRate;
private Double fMinReserveRate;
private Double fMaxForePayAmount;
private Double fMaxForePayRate;
private Integer fDebtLevel;
private Integer fCreditDays;
private BigDecimal fValueAddRate;
private Integer fPayTaxAcctId;
private BigDecimal fDiscount;
private Integer fTypeId;
private BigDecimal fCreditAmount;
private String fCreditLevel;
private Integer fStockIdAssignee;
private Integer fBr;
private String fRegmark;
private Boolean fLicAndPermit;
private String fLicence;
private Date fPaperPeriod;
private Integer fAlarmPeriod;
private Integer fOtherArAcctId;
private Integer fOtherApAcctId;
private Integer fPreArAcctId;
private String fHelpCode;
private Timestamp fModifyTime;
private Integer fCreditDegree;
private String fRightUserId;
private Integer fPaymentTime;
private String fSMSPhoneNumber;
private String fFullName;
}

@ -1,7 +1,9 @@
package com.lyr.gather.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lyr.gather.domain.vo.DataSourceConfig;
import com.lyr.gather.domain.model.DataSourceConfig;
public interface DataSourceConfigMapper extends BaseMapper<DataSourceConfig> {
}

@ -0,0 +1,25 @@
package com.lyr.gather.mapper;
import com.lyr.common.annotation.DataSource;
import com.lyr.gather.domain.model.TSupplier;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface TSupplierMapper {
@DataSource(name = "#dataSource")
@Select("SELECT " + //
"s.FItemID, " + //
"s.FSaleMode, " + //
"s.FName, " + //
"s.FNumber, " + //
"s.FParentID, " + //
"s.FShortNumber, " + //
"s.FHelpCode, " + //
"s.FFullName " + //
"FROM t_Supplier s")
List<TSupplier> list(@Param("dataSource") String dataSource);
}

@ -1,11 +1,13 @@
package com.lyr.gather.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lyr.gather.domain.vo.DataSourceConfig;
import com.lyr.gather.domain.model.DataSourceConfig;
public interface DataSourceConfigService extends IService<DataSourceConfig> {
void print();
void add();
void list(String s, Object o);
}

@ -2,9 +2,10 @@ package com.lyr.gather.service.impl;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyr.framework.manager.DataSourceManagerService;
import com.lyr.gather.domain.vo.DataSourceConfig;
import com.lyr.framework.manager.DataSourceManager;
import com.lyr.gather.domain.model.DataSourceConfig;
import com.lyr.gather.mapper.DataSourceConfigMapper;
import com.lyr.gather.mapper.TSupplierMapper;
import com.lyr.gather.service.DataSourceConfigService;
import org.springframework.stereotype.Service;
@ -16,7 +17,10 @@ import java.util.List;
public class DataSourceConfigServiceImpl extends ServiceImpl<DataSourceConfigMapper, DataSourceConfig> implements DataSourceConfigService {
@Resource
private DataSourceManagerService dataSourceManagerService;
private DataSourceManager dataSourceManager;
@Resource
private TSupplierMapper tSupplierMapper;
@PostConstruct
private void registered() {
@ -27,22 +31,29 @@ public class DataSourceConfigServiceImpl extends ServiceImpl<DataSourceConfigMap
dataSource.setUrl(e.getUrl());
dataSource.setUsername(e.getUsername());
dataSource.setPassword(e.getPassword());
dataSourceManagerService.registerDataSources(e.getBeanName(), dataSource);
dataSource.setName(e.getBeanName());
dataSourceManager.defaultDataSourceConfiguration(dataSource, DataSourceManager.RegisterType.LOAD);
});
}
@Override
public void print() {
dataSourceManagerService.print();
dataSourceManager.print();
}
@Override
public void add() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:sqlserver://192.168.3.28:1433;DatabaseName=BiDataDeYue;encrypt=true;trustServerCertificate=true;");
dataSource.setUrl("jdbc:sqlserver://192.168.3.28:1433;DatabaseName=KIS;encrypt=true;trustServerCertificate=true;");
dataSource.setUsername("sa");
dataSource.setPassword("mssql_whdZeB");
dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
dataSourceManagerService.registerDataSources("biDataDeYue", dataSource);
dataSource.setName("sqlserver");
dataSourceManager.defaultDataSourceConfiguration(dataSource, DataSourceManager.RegisterType.ADD);
}
@Override
public void list(String datasourceName, Object o) {
tSupplierMapper.list(datasourceName);
}
}

Loading…
Cancel
Save