前言
最近项目,需要根据不同的数据源类型来对数据库进行操作。我在一个接口定义了数据源应该有的操作(如:获取schema,获取某个库下的所有表)
由于实现的方法,每种类型的数据源都不太一样。比方说mysql数据预览的sql是用limit来限制返回条数,而oracle用rownum来做。这里根据数据源类型来返回具体的实现类。踩了一些雷也在这里记录一下。
1.开始指定接口及实现类
public interface DbService<T> {
String getType();
T kvToObj();
// 以下是其他方法
}
@Component
public class MysqlImpl implements DbService {
@Override
public String getType() {
return DbTypeEnum.MYSQL.getDbType();
}
@Override
public Object kvToObj() {
return null;
}
}
@Component
public class OracleImpl implements DbService {
@Override
public String getType() {
return DbTypeEnum.ORACLE.getDbType();//这个方法判定当前实现的是那种数据源类型
}
@Override
public Object kvToObj() {
return null;
}
}
雷点1:这里的实现类最好注解一下@Component 使spring启动项目时能自动装配。因为实现类可能需要@autowired别的service,可能导致autowired空指针的问题(这个坑可能跟我下文说的new方法有关系,这里标记1)。
2.枚举类
public enum DbTypeEnum {
MYSQL("MySQL"), ORACLE("Oracle");
private String dbType;
DbTypeEnum(String dbType) {
this.dbType = dbType;
}
public String getDbType() {
return dbType;
}
public void setDbType(String dbType) {
this.dbType = dbType;
}}
3.工场 实现 ApplicationContextAware的方法
@Component
public class DbFactory implements ApplicationContextAware {
private static Map<String, DbService> beanMap;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String,DbService> map = applicationContext.getBeansOfType(DbService.class);
beanMap = new HashMap<>();
map.forEach((key,value)->beanMap.put(value.getType(),value));
}
// 静态方法 直接调用即可
public static <T extends DbService> T chooseDb(String dbType){
return (T) beanMap.get(dbType);
}
}
这里setApplicationContext 的方法在启动项目的时候就会把所有的实现类装配进去。
雷点2:一开始我是用switch判断数据源类型,然后用 父类 a = new 子类 的方法,这种方法跳过了spring的装配,后续可能用到autowired时候报空指针(标记1),所以弃用。