Java JDBC基本概念、池和线程

Java JDBC基本概念、池和线程,java,oracle,multithreading,jdbc,connection-pooling,Java,Oracle,Multithreading,Jdbc,Connection Pooling,我总是在单线程环境中使用JavaSE中的JDBC。但现在我需要使用一个连接池,让许多线程与数据库(MSSQL和Oracle)进行交互,我很难做到这一点,因为我似乎对api缺乏一些基本的了解 连接并记录后的AFAIK连接表示与数据库的物理tcp/ip连接。它创建的语句可以看作是通过连接与数据库的SQL交互 事务和回滚从何而来?是在连接还是语句级别 “一个”Connection创建N个语句并将其提供给不同的线程,以便让每个线程都拥有该语句的使用权,这样安全吗 如果没有,则在配置池后,如下所示:

我总是在单线程环境中使用JavaSE中的JDBC。但现在我需要使用一个连接池,让许多线程与数据库(MSSQL和Oracle)进行交互,我很难做到这一点,因为我似乎对api缺乏一些基本的了解

连接并记录后的AFAIK
连接
表示与数据库的物理tcp/ip连接。它创建的
语句可以看作是通过
连接与数据库的SQL交互

  • 事务和回滚从何而来?是在
    连接
    还是
    语句
    级别
  • “一个”
    Connection
    创建N个语句并将其提供给不同的线程,以便让每个线程都拥有该
    语句的使用权,这样安全吗
如果没有,则在配置池后,如下所示:

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();
//线程结束运行方法

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();
  • 如果池的任何物理连接以某种方式崩溃或断开,池是否会自动尝试重新连接并将新连接注入池中,以便后续的Pool.getConnection()只获得健康连接
非常感谢,请原谅我的英语不好

  • 事务发生在连接级别

  • 不可以。通常,JDBC驱动程序会确保在另一条语句处于活动状态时,不能在同一个连接上执行第二条语句

  • 如果需要连接池,请尝试。它提供了相当不错的故障处理(比如注意陈旧的连接和客户端代码未返回的连接)

    至于您的代码:始终将代码包装在
    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;
    }
    

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

    我认为您应该从Sun on connection pooling开始。除此之外,还有许多连接池的实现,一些是开源的,包括。你真的应该从这里开始,而不是在这里重新发明轮子。

    连接池用它们自己的包装器实现装饰连接和语句实例。当您在连接上调用close时,实际上只是将其释放回池中。在对准备好的语句调用close时,实际上只是将其释放回连接的语句缓存。准备语句时,可能只是从连接中获取缓存语句实例。所有这些都隐藏在视线之外,所以你不必担心

    将连接提供给客户端时,在将连接释放回池之前,任何其他客户端都无法再使用该连接。通常,您只需在需要连接时获取连接,然后在完成连接后立即返回。因为连接在池中保持打开状态,所以获取和释放连接的开销很小

    您应该像使用单个JBDC连接一样使用池中的连接,并遵循有关关闭资源的最佳实践,以避免泄漏任何连接或语句。请参阅其他一些答案中的try/catch/finally示例


    池可以管理连接资源并在将它们分发给客户端之前对其进行测试,以确保它们不会过时。此外,池将根据需要创建和销毁连接。

    在任何给定的连接上,只能保持一条语句处于打开状态。使用连接池创建多个连接并不困难,尽管方法是使用其中一个更常用的连接

    此外,如果您打算采用标准JDBC,我建议使用PreparedStatement而不是Statement

    我一直在使用iBatis,开箱即用非常好。还带来了一些其他的东西

    看看(+:

    额外的位:

  • 应用服务器倾向于提供连接池,它可以变得非常聪明。如果你正在使用应用服务器,在添加任何你自己的东西之前,仔细调查你从盒子里得到了什么

  • 交易:如果你有

    开始交易

    接通 工作 关闭连接//意味着返回池

    获取连接(具有相同的隔离级别等)
    //您将获得相同的连接,池将为您的交易保留该连接

    工作/发生在同一交易中 密切联系

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

  • 连接和错误


  • 池实现可能很聪明。如果池中的任何一个连接遇到某些错误,表明DB服务器已反弹,那么池可以选择放弃所有池成员。

    如果您已经掌握了单线程JDBC,那么使用多线程和连接池应该不是什么大问题。您需要做的就是不同的是:1.当你需要连接时,从池中获取,而不是直接获取。2.每个线程都应该有自己的连接

    澄清第2点:如果您获得一个连接,然后将其传递给多个线程,那么可能会有两个线程同时尝试对同一个连接执行查询。Java将对此抛出异常。每个连接只能有一个活动语句和一个活动查询(即ResultSet)如果两个线程都持有相同的连接对象,它们很可能会立即违反此规则

    还有一个警告:使用连接池时,请务必非常小心地在完成连接后关闭连接。池管理器没有确定的方法来关闭连接