對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

相關文章
相關標籤/搜索