JDBC - 连接多个数据库

时间:2010-08-06 21:09:22

标签: java database jdbc

我正在开发一个应用程序,我需要连接N个数据库系统[N范围在1到350之间]。

这个想法是 - 将向用户显示数据库列表,并要求用户从列表中选择任何或所有数据库。

选择数据库后,我需要连接到每个数据库并执行存储过程。

我打算使用普通的旧JDBC并且每次都为它们获取连接[或者通过在多个线程中运行它们]并执行存储过程并关闭连接。

所有这一切都应该在交易中发生。这样做的最佳方式是什么?

如果不是JDBC ......还有其他任何有效的方法吗?

更新 -

存储过程实际上涉及运行某些sql - 例如更新列,为用户授予权限等。

5 个答案:

答案 0 :(得分:3)

我创建了一个具有合理最大线程数量的线程池,可以在Executors#newFixedThreadPool()的帮助下,在10到20个线程之间,并调用单独的DB连接和SP执行任务,每个任务为Callable使用ExecutorService#invokeAll()。你想玩线程数和配置文件,毕竟产生最佳性能。

每个Callable实现都应该将连接详细信息和SP名称作为构造函数参数,以便您可以为不同的数据库调用重用相同的实现。


更新:好的,这是一个网络应用程序。你不想浪费线程。如果它应该由单个并发用户使用,那么您应该确保线程池在请求结束时或在会话的最高端正确shutdown。但是如果它应该由多个并发用户使用,那么您希望在应用程序范围内共享线程池。此外,您还需要确保在webapp关闭时正确关闭它。 ServletContextListener在这里很有用。

答案 1 :(得分:2)

如果您可以使用两个连接,请使用连接池c3p0来管理它们。要连接两个数据库,我声明:

public Connection connection1;
public Connection connection2;
DataSource dataSource1;
DataSource dataSource2;

然后有两种类似的方法:

public Connection dbConnect1() throws SQLException {
    ComboPooledDataSource cpds = new ComboPooledDataSource();
    try {
        cpds.setDriverClass("com.mysql.jdbc.Driver");
    } catch (PropertyVetoException e) {
    }
    cpds.setJdbcUrl("jdbc:mysql://localhost:3306/myDatabase1?autoReconnect=true"); 
    cpds.setUser("myMYSQLServerLogin");
    cpds.setPassword("myMYSQLServerPassword");
    cpds.setMinPoolSize(5);
    cpds.setAcquireIncrement(5);
    cpds.setMaxPoolSize(20);
    cpds.setMaxIdleTime(60);
    cpds.setMaxStatements(100);
    cpds.setPreferredTestQuery("SELECT 1");
    cpds.setIdleConnectionTestPeriod(60);
    dataSource1 = cpds;
    connection1 = dataSource1.getConnection();
    return connection1;
}

public Connection dbConnect2() throws SQLException {
    ComboPooledDataSource cpds = new ComboPooledDataSource();
    try {
        cpds.setDriverClass("com.mysql.jdbc.Driver");
    } catch (PropertyVetoException e) {
    }
    cpds.setJdbcUrl("jdbc:mysql://localhost:3306/myDatabase2?autoReconnect=true"); 
    cpds.setUser("myMYSQLServerLogin");
    cpds.setPassword("myMYSQLServerPassword");
    cpds.setMinPoolSize(5);
    cpds.setAcquireIncrement(5);
    cpds.setMaxPoolSize(20);
    cpds.setMaxIdleTime(60);
    cpds.setMaxStatements(100);
    cpds.setPreferredTestQuery("SELECT 1");
    cpds.setIdleConnectionTestPeriod(60);
    dataSource2 = cpds;
    connection2 = dataSource2.getConnection();
    return connection2;
}

答案 2 :(得分:1)

正如duffymo在他的评论中所指出的,如果你有一个事务协调员和两个阶段提交,你将只能跨多个数据库进行交易。

为此,您需要一个可以处理JTA的J2EE堆栈。如果您在Tomcat或其他没有JTA的容器中运行,则可以下载并安装多个选项。

当然,您需要让Container而不是数据库/存储过程处理事务提交和回滚。

答案 3 :(得分:0)

这听起来像是一团糟,但这是你的问题。

每个数据库需要一个连接池。我不建议您尝试自己处理连接生命周期。让app服务器为您完成。

如果您希望一组数据库参与一个大型事务,则必须使用JDBC XA驱动程序来所有。您还需要一个JTA事务管理器来监督您的交易。

存储过程不能包含任何处理事务的逻辑;你必须让JTA这样做。

您没有说明存储过程正在做什么。如果它不需要返回任何内容,则替代设计可能是JMS,队列和侦听器池。如果我是你,我会担心线程问题。如果可能的话,我会找到一种方法让容器做那些复杂的事情。

答案 4 :(得分:0)

public static Connection getconnection(String db,String host){
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://"+**Pass Your Host Here 
Like Localhost**+"/"+Pass Your DB Name** +"?useUnicode=yes&characterEncoding=UTF- 
8","root","root");
return con;
} catch (ClassNotFoundException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} 
}