对AutoTableBindPlugin的一点改造使它支持多数据源

在使用jFinal的时候由于不想每一个Model都一个个去写映射关系,所以使用了@绝望的八皮 的AutoTableBindPlugin来自动绑定Model与表之间的映射,可是在jFinal升级到1.6后AutoTableBindPlugin不支持多数据源,所以对AutoTableBindPlugin作了小小的一点改造使它支持多数据源。java

由于在使用AutoTableBindPlugin的时候它会检索到全部继承Model类的子类来进行绑定映射关系。所以在配置多个AutoTableBindPlugin的时候前面配置的AutoTableBindPlugin会加载后面配置的AutoTableBindPlugin中其余数据源的Model这个时候就报错了,提示找不到表了!数据库

个人解决办法是添加一个包扫描的方法以及在AutoTableBindPlugin的构造方法中添加一个configName的参数app

public class AutoTableBindPlugin extends ActiveRecordPlugin {
    protected final Logger log = Logger.getLogger(getClass());
    @SuppressWarnings({"unchecked" })
    private List<Class<? extends Model>> excludeClasses = Lists.newArrayList();
    private List<String> packageList = Lists.newArrayList(); 
    private List<String> includeJars = Lists.newArrayList();
    private boolean autoScan = true;
    private boolean includeAllJarsInLib;
    private INameStyle nameStyle;
    public AutoTableBindPlugin(DataSource dataSource) {
        this(dataSource, SimpleNameStyles.DEFAULT);
        
    }
    public AutoTableBindPlugin(DataSource dataSource, INameStyle nameStyle) {
        super(dataSource);
        this.nameStyle = nameStyle;
    }
    
    public AutoTableBindPlugin(String confitName,DataSource dataSource, INameStyle nameStyle) {
     super(confitName,dataSource);
     this.nameStyle = nameStyle;
    }
    public AutoTableBindPlugin(IDataSourceProvider dataSourceProvider,String... packages) {
        this(dataSourceProvider, SimpleNameStyles.DEFAULT);
    }
    public AutoTableBindPlugin(IDataSourceProvider dataSourceProvider, INameStyle nameStyle) {
        super(dataSourceProvider);
        this.nameStyle = nameStyle;
    }
    
    public AutoTableBindPlugin(String configName,IDataSourceProvider dataSourceProvider, INameStyle nameStyle) {
        super(configName,dataSourceProvider);
        this.nameStyle = nameStyle;
    }
    @SuppressWarnings({"unchecked"})
    public AutoTableBindPlugin addExcludeClasses(Class<? extends Model>... clazzes) {
        for (Class<? extends Model> clazz : clazzes) {
            excludeClasses.add(clazz);
        }
        return this;
    }
    @SuppressWarnings({"unchecked" })
    public AutoTableBindPlugin addExcludeClasses(List<Class<? extends Model>> clazzes) {
        if (clazzes != null) {
            excludeClasses.addAll(clazzes);
        }
        return this;
    }
    public AutoTableBindPlugin addJars(List<String> jars) {
        if (jars != null) {
            includeJars.addAll(jars);
        }
        return this;
    }
    public AutoTableBindPlugin addJars(String... jars) {
        if (jars != null) {
            for (String jar : jars) {
                includeJars.add(jar);
            }
        }
        return this;
    }
    
    public AutoTableBindPlugin scanPackages(String...packages){
       if(packages != null){
          for (String pack : packages) {
             packageList.add(pack);
          }
       }
       return this;
    }
    
    @Override
    @SuppressWarnings({"unchecked"})
    public boolean start() {
        List<Class<? extends Model>> modelClasses = ClassSearcher.of(Model.class).injars(includeJars).includeAllJarsInLib(includeAllJarsInLib).search();
        TableBind tb = null;
        for (Class modelClass : modelClasses) {
            //指定了扫描包的状况下根据包名来进行加载映射关系,不然就所有加载
            if(!packageList.isEmpty()){
                for (String pack : packageList) {
                   if(modelClass.getName().startsWith(pack)){
                      scanModel(tb,modelClass);
                   }
                }
            }else{
               scanModel(tb,modelClass);
            }
        }
        return super.start();
    }
    @Override
    public boolean stop() {
        return super.stop();
    }
    @SuppressWarnings({ "unchecked"})
 private void scanModel(TableBind tb,Class clazz){
     if (!excludeClasses.contains(clazz)) {
         tb = (TableBind) clazz.getAnnotation(TableBind.class);
         String tableName;
         if (tb == null) {
             if (autoScan) {
              tableName = nameStyle.name(clazz.getSimpleName());
              this.addMapping(tableName, clazz);
              log.debug("addMapping(" + tableName + ", " + clazz.getName() + ")");
             }
         } else {
             tableName = tb.tableName();
             if (StringKit.notBlank(tb.pkName())) {
                 this.addMapping(tableName, tb.pkName(), clazz);
                 log.debug("addMapping(" + tableName + ", " + tb.pkName() + "," + clazz.getName() + ")");
             } else {
                 this.addMapping(tableName, clazz);
                 log.debug("addMapping(" + tableName + ", " + clazz.getName() + ")");
             }
         }
     }
    }
    
    public AutoTableBindPlugin autoScan(boolean autoScan) {
        this.autoScan = autoScan;
        return this;
    }
    public AutoTableBindPlugin includeAllJarsInLib(boolean includeAllJarsInLib) {
        this.includeAllJarsInLib = includeAllJarsInLib;
        return this;
    }

这样改造以后若是你没有使用多数据源的话就和原来同样不须要任何变化,若是有多数据源的话你就只须要配置一个你处在不一样package下的多数据源的Model以及一个configName就好了:ide

例如:数据源datasource1的model处在com.test.model.ds1下this

//自动绑定数据库表()
      AutoTableBindPlugin atbp1= new AutoTableBindPlugin(c3p0Plugin1,SimpleNameStyles.LOWER);
      //扫描com.test.model.ds1下的model
      atbp1.scanPackages("com.test.model.ds1");
      atbp1.setShowSql(true);
      //不扫描没有注解的Model类
      atbp1.autoScan(false);
      me.add(atbp1);

此处没有配置configName表示的是主数据源,也能够配置一个.net

若是数据源datasource2的model处在com.test.model.ds2下就在上面代码中只须要改变这两个地方就行。以下:debug

//指定configName以及相应的数据源配置
AutoTableBindPlugin atbp2= new AutoTableBindPlugin("configName",c3p0Plugin2,SimpleNameStyles.LOWER);
//指定须要扫描的包名
atbp2.scanPackages("com.test.model.ds2");

这样的好处就是若是你项目以前没有使用多数据源原来的代码不须要任何改变,后面才加入的多数据源的话你只须要配置下这个数据源下Model所在的包名就好了,就算你某个数据源的Model分散在几个包下atbp1.scanPackages("xxx.xxx1","xxx.xxx2")也是能够配置多个的。若是你多个数据源的Model都放在某个包下,那.... 只能说你包结构有些混乱了至少要区分下吧,这样的话你仍是一个Model一个Model的映射吧,或许有更好的解决办法。目前我以为这样仍是挺方便的。
code

相关文章
相关标签/搜索