由于公司业务要求,项目要求同时支持区块链和传统关系型数据库,由于区块链的特殊特性,每次 *** 作的时候需要将表名作为参数进行接口调用,并且所有的方法都是抽出统一管理,所以在适配Mybatis-Plus的时候便遇到了不能将实现类和表名进行一一对应的情况,于是就有了下面的动态返回Mybatis-Plus的IService,返回的接口取决于传入的表名。
1、建立数据工厂选择器
建立DataBaseFactory类,该类用于根据配置文件中配置的数据存储方式来判断创建那种方式
public class DataBaseFactory {
public static boolean isConnecting = false;
public static IDataBaseCommon build() {
IDataBaseCommon dataBaseCommon = null;
// 这里是从配置文件中取出该应用需要使用那种数据存储模式
String dataBaseType = (String) ProcessConfCom.getCommonYml("database.sqlImpl");
// 区块链
if (Constants.CONFIG_DATABASE_IMPL_CHAINSQL.equals(dataBaseType)) {
...
}
// 达梦数据库
if (Constants.CONFIG_DATABASE_IMPL_DM.equals(dataBaseType)) {
return new DmDbCommonImpl();
}
// mysql
if (Constants.CONFIG_DATABASE_IMPL_MYSQL.equals(dataBaseType)) {
// 同达梦数据库
}
return dataBaseCommon;
}
}
2、达梦(mysql)数据库工厂
建立DmServerFactory类,该类管理所有需要处理的表对应的实现类,根据传入的表名进行选择返回那种IService的实现类
@Component
public class DmServerFactory {
@Autowired
ConfigCertOrgServer configCertOrgServer;
@Autowired
ConfigFisServer configFisServer;
@Autowired
ConfigSubServer configSubServer;
@Autowired
TransAttachServer transAttachServer;
@Autowired
TransInfoServer transInfoServer;
@SuppressWarnings("rawtypes")
public IService build(String tableName) {
if (Constants.TABLE_CSJ_CONFIG_CERT_ORG.equals(tableName)) {
return this.configCertOrgServer;
}
if (Constants.TABLE_CSJ_CONFIG_FIS.equals(tableName)) {
return this.configFisServer;
}
if (Constants.TABLE_CSJ_CONFIG_SUB.equals(tableName)) {
return this.configSubServer;
}
if (tableName.contains("trans_attach")) {
return this.transAttachServer;
}
if (tableName.contains("trans_info")) {
return this.transInfoServer;
}
return new ServiceImpl();
}
}
3、具体实现类
这里就是通用的公共方法,只要传入表名,通过dmServerFactory.build();即可返回我们需要的接口,该接口调用的mybatis的方法就是我们需要 *** 作表的方法。
@Slf4j
@Service("DmDbCommonImpl")
public class DmDbCommonImpl implements IDataBaseCommon {
@SuppressWarnings("rawtypes")
@Override
public void saveDataByTable(String tableName) {
// 由于工厂模式的原因,入口类的构造函数哪里不能进行自动注入交给spring进行管理,所以这里通过应用上下文返回
DmServerFactory dmServerFactory = ApplicationContextProvider.getBean(DmServerFactory.class);
JSONObject jsonObject = new JSONObject();
IService iService = dmServerFactory.build(tableName);
// 这里返回的IService就可以进行我们熟悉的 *** 作了,并且所 *** 作的就是传入的tableName
boolean b = iService.saveBatch(saveList);
...
}
}
4、ApplicationContextProvider类
通过应用上下文获取实例的方法,也分享一下吧
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* 普通类中无法注入service问题解决方案
*/
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
/**
* 上下文对象实例
*/
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextProvider.applicationContext = applicationContext;
}
/**
* 获取applicationContext
*
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通过name获取 Bean.
*
* @param name
* @return
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 通过class获取Bean.
*
* @param clazz
* @param
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 通过name,以及Clazz返回指定的Bean
*
* @param name
* @param clazz
* @param
* @return
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
5、工厂模式入口
利用构造函数进行创建,因为build()方法会的实现类是不确定的,所以这里不能交给spring进行管理(或许是我没搞明白),启动的时候会报出注入的对象含有多个实现类,无法确定需要注入的是哪个。
@Slf4j
@SuppressWarnings("rawtypes")
public class UploadAttachAsyncJob {
private IDataBaseCommon dataBaseCommon;
// 构造函数,类加载时候会触发该函数,调用DataBaseFactory.build()
public UploadAttachAsyncJob(IOpFileUploadCommon opFileCommon) {
this.dataBaseCommon = DataBaseFactory.build();
}
// 这里就可以根据传入的表名直接调用通用方法
public void save(String tableName){
dataBaseCommon.saveDataByTable(tableName);
}
}
不足之处,多多指教~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)