2013-04-26 79 views
0

我无法找到适当的解决方案:来自不同数据源或数据库的异步多个查询

我有几个数据库具有相同的结构,但具有不同的数据。当我的Web应用程序执行查询时,它必须为每个数据库分开此查询并异步执行,然后汇总来自所有数据库的结果并将其作为单一结果返回。另外我想能够传递一个数据库的列表,其中将执行查询,并且我希望传递查询执行的最大过期时间。结果还必须包含每个数据库的元信息,例如超额执行时间。

如果可以使用其他数据源(如具有特定API的远程Web服务而不是关系数据库),那将会很棒。

我使用Spring/Grail并需要Java解决方案,但我会很乐意提供任何建议。

UPD:我想找到准备好的解决方案,也许框架或类似的东西。

+0

好的,问题是什么?你有什么尝试?什么阻止你这样做? – 2013-04-26 10:09:33

+0

所以,我想找到准备好的解决方案,也许框架或类似的东西。但只有一件事我发现它是UnityJDBC,但它只适用于关系数据库,并没有元信息和查询到期时间 – 2013-04-26 10:56:17

回答

2

这是基本的OO。您需要抽象出您正在尝试实现的内容 - 从您使用的机制中加载数据 - 实现数据库查询或Web服务调用。

这样的设计通常会涉及一个接口,该接口定义可以完成什么的合同,然后是根据其实现情况实现的多个实现类。

例如,你想最终,看上去像一个接口:

public interface DataLoader 
{ 
    public Collection<Data> loadData() throws DataLoaderException; 
} 

那么你将不得不实现比如JdbcDataLoaderWebServiceDataLoader等。在你的情况,你就需要另一种类型的实现是给定DataLoader的一个或多个实例,每个运算每个累计汇总结果。这个实现看起来像这样:

public class AggregatingDataLoader implements DataLoader 
{ 
    private Collection<DataLoader> dataLoaders; 
    private ExecutorService executorService; 

    public AggregatingDataLoader(ExecutorService executorService, Collection<DataLoader> dataLoaders) 
    { 
    this.executorService = executorService; 
    this.dataLoaders = dataLoaders; 
    } 

    public Collection<Data> loadData() throws DataLoaderException 
    { 
    Collection<DataLoaderCallable>> dataLoaderCallables = new ArrayList<DataLoaderCallable>>(); 

    for (DataLoader dataLoader : dataLoaders) 
    { 
     dataLoaderCallables.add(new DataLoaderCallable(dataLoader)); 
    } 

    List<Future<Collection<Data>>> futures = executorService.invokeAll(dataLoaderCallables); 

    Collection<Data> data = new ArrayList<Data>(); 
    for (Future<Collection<Data>> future : futures) 
    { 
     add.addAll(future.get()); 
    }  

    return data; 
    } 

    private class DataLoaderCallable implements Callable<Collection<Data>> 
    { 
    private DataLoader dataLoader; 

    public DataLoaderCallable(DataLoader dataLoader) 
    { 
     this.dataLoader = dataLoader; 
    } 

    public Collection<Data> call() 
    { 
     return dataLoader.load(); 
    } 
    } 
} 

你需要添加一些超时和异常处理逻辑,但你得到的主旨。

另一个重要的是你的通话代码应该只使用DataLoader接口,这样你就可以在测试过程中交换不同的实现或者使用模拟。

+0

感谢您的详细解答。我同意,实现起来并不困难,但我认为我可以为我的案例找到像mapreduce框架(如hadoop)。但似乎我必须自己写。 – 2013-04-26 12:22:25

+1

做map-reduce的工作是知道如何映射要减少的数据集和reduce本身 - 两者都将针对您的问题。像Hadoop或大多数分布式缓存技术一样会执行map-reduce,但您仍然在实现他们的接口来完成实际的工作。我的建议,如果你可以很容易地做到这一点,而不是引入一个框架(附加依赖),然后保持简单并忽略框架。 – 2013-04-26 12:33:57