JDBC基本概念,池和线程(JDBC fundamental concepts, Pooling a

2019-08-01 03:42发布

我总是在JavaSE中使用单线程环境JDBC。 但现在我需要使用连接池,让许多线程与数据库(MSSQL和Oracle)的相互作用,我有一个很难试图让它,因为它似乎我缺少API的一些基本undestanding。

据我所知后连接,并记录一个Connection代表一个物理性的TCP / IP连接到数据库。 它创建Statement (S),可以被看作是SQL的相互作用(S)与数据库在Connection

  • 哪里事务和回退自带的? 它是在ConnectionStatement的水平。
  • 它是安全的是“一” Connection创建n个语句,并给它diferent线程,以便让每一个拥有使用该的Statement

如果不是,和配置池是这样的后:

OracleDataSource ods = new OracleDataSource(); 
ods.setURL("jdbc:oracle:thin:@tnsentryname");
ods.setUser("u");
ods.setPassword("p");
  • 顺便说一句,我在哪里设置连接池的大小?

  • 难道这就是我想在每个线程,以便正确地使用连接在做什么?

// THEAD run方法

Connection conn = ods.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("the sql");
// do what I need to do with rs
rs.close();
int updateStatus = stmt.executeUpdate("the update");
stmt.close();
conn.close();

//线程运行方法的端

  • 如果池的任何物理连接莫名其妙地死机或disconects,将池automaticaly尝试重新连接并注入池中的新连接,以使后续pool.getConnection()只会得到一个健康的连接?

非常感谢,原谅我的英语不好请。

Answer 1:

连接池装饰Connection和Statement情况下用自己的包装实现。 当你调用一个紧密连接上你实际上只是将其释放回池中。 当你调用close在一份声明中,你实际上只是将其释放回连接的语句缓存。 当您准备一份声明中你可能只是取出由连接高速缓存的语句实例。 所有这一切都隐藏起来,这样你就不必担心。

当连接被提供给客户端不再适用于任何其他客户端使用,直到连接被释放回池中。 当你需要的时候你一般只是获取连接,然后当你对它们操作结束后立即归还。 因为连接正在举行开放池中存在获取和释放连接小的开销。

您应该使用从泳池就像你一个JBDC连接的连接,并按照有关资源的关闭,这样你就不会泄漏任何连接或声明的最佳实践。 见的try / catch /终于在一些其他的答案的例子。

池可以管理连接资源,并交给他们,向客户确保他们不会过时之前对其进行测试。 另外一个池将根据需要创建和销毁连接。



Answer 2:

如果你已经掌握JDBC与单线程,要多线程和连接池不应该是一个大问题。 所有你需要做的是不同的:1,当你需要一个连接,从池中,而不是直接得到它。 2.每个线程应该得到自己的连接。

为了澄清点2:如果你得到一个连接,然后把它传递给多个线程,你可以有两个线程试图对在同一时间在同一个连接执行查询。 Java将抛出这个异常。 你只能有每个连接的一个活动语句和每一个语句活动查询(即结果集)。 如果两个线程都持有相同的Connection对象,他们很可能会迅速违反此规则。

另外一个需要注意:使用连接池是非常非常小心,始终关闭连接时,即可大功告成。 池管理有没有明确的办法知道当你与一个连接来完成,因此,如果您不能关闭一个,它会坐在那里晃来晃去很长一段时间,可能是永远取决于池管理器。 我总是总是始终遵循每一个“的getConnection”有try块,并关闭在finally块的连接。 后来我知道,我已经在函数退出前关闭它。

除此之外,一切都应该是一样的,你已经习惯了的东西。



Answer 3:

  1. 交易发生在连接级别。

  2. 号通常情况下,JDBC驱动程序将确保,而另外一个是积极的,你不能在同一个连接上执行第二次发言。

如果您需要连接池,尝试DBCP框架 。 它提供了相当不错的失败处理(如注意到失效连接并没有被客户端代码返回连接)。

至于你的代码:始终包裹在代码try{...}finally{...}

Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
     conn = ds.getConnection ();
     stmt = ...
     rs = ...
}
finally {
     rs = close (rs);
     stmt = close (stmt);
     conn = close (conn);
}

public static Connection close (Connection conn) {
    if (conn != null) {
        try {
            conn.close ();
        }
        catch (SQLException e) {
            e.printStackTrace(); // Log, don't rethrow!!
        }
    }
    return null;
}

此代码将确保所有连接等,始终正确关闭,并且在关闭任何异常不会隐藏以前的错误。



Answer 4:

我想你应该与Sun开始教程上的连接池。 除此之外,还有连接池,一些开源,其中的许多实现Apache的一个 。 你真的应该从这里开始,而不是在这里推倒重来。



Answer 5:

你可以只留一个声明在任何给定的连接打开。 创建使用连接池一个以上的连接并不困难,虽然要走的路是用更大的用过的旧之一在那里。

另外,如果你要去标准的JDBC的方式,我建议使用PreparedStatement的过声明。

我一直在使用iBATIS和开箱即用的是相当不错的。 带来了一些其他的事情表为好。



Answer 6:

采取甘德在此 (+:



Answer 7:

额外资料:

  1. 应用服务器往往提供连接池,它可以得到相当聪明。 如果您使用的是应用服务器仔细调查您将自己的任何事情之前得到的开箱即用。

  2. 交易方式:如果你有

    开始交易

    得到connnection工作紧密结合//意味着回归到池

    获取连接(与同一隔离级别等)
    //你会得到相同的连接,池保留它为您的交易

    工作//发生在同一transacction紧密结合

    提交事务//提交的所有工作

  3. 连接和错误

池实现可以巧妙。 如果从池中的任何一个连接遇到某些错误,这表明该数据库服务器已经反弹则池可以选择放弃所有池成员。



文章来源: JDBC fundamental concepts, Pooling and Threading