java程序访问数据库,dbcp连接池,hibernate连接总是报池连接用光了/JDBC连接没有报错

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java程序访问数据库,dbcp连接池,hibernate连接总是报池连接用光了/JDBC连接没有报错相关的知识,希望对你有一定的参考价值。

池连接用光了,可以重启连接池,是没问题,后来用hibernate访问过多是时候Oracle数据库有时候会拒接访问,说是超过数据库连接最大数
dbcp连接数:20
hibernate : tx.commit ; session.colse()
JDBC : conn/proc/result/stam.colse();s
是不是hibernate本身程序问题?
同是一个连接池,hibernate一些 连接没有关闭?JDBC关闭的很好
只用了hibernate,没有Spring

加断点调试一下了,这个情况99%是你创建了数据库连接对象后,用完没有close。追问

调试,看看吧,在哪里colse,session.colose()不行??还是在hibernate 里面调用(增删查改)方法之前的连接??

追答

session.close(); 是这个关闭。。 你检查下是不是有地方写错了 ,没有关闭。或关闭不了 。

建议加spring去管理这些。自己不用去控制事物了

参考技术A 那你每次打开连接,有没有关闭呢追问

session.colse()不行??是hibernate里面??

追答

关闭,是con.close(),

参考技术B

java dbcp2多线程连接访问

我对在Tomcat上使用连接池非常熟悉,并且已经使用了好几年没有问题。但是,目前我正在开发一个主要方法应用程序,出于性能原因,该应用程序需要同时运行线程,并且这些线程每个都需要访问同一数据库。如果我完全删除数据库代码,并且只是将数组用于测试目的(例如,多线程工作),那么我的代码就可以工作,但是一旦我重新添加数据库连接,第一个线程就会获得锁,而其他线程则不会根本不跑。已经玩过c3p0和dbcp2;当前正在使用dbcp2。谢谢!那里有大量的文档,但是似乎没有很多用例专用的代码示例。这是一个示例应用程序:

import java.sql.*;
import org.apache.commons.dbcp2.ConnectionFactory;
import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
import org.apache.commons.dbcp2.PoolableConnection;
import org.apache.commons.dbcp2.PoolableConnectionFactory;
import org.apache.commons.dbcp2.PoolingDataSource;
import org.apache.commons.dbcp2.PoolingDriver;
import org.apache.commons.dbcp2.Utils;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPool;

public class SandboxApp {

    private static BasicDataSource dataSource;

    public static BasicDataSource getDataSource() {

        if (dataSource == null) {

            BasicDataSource ds = new BasicDataSource();

            ds.setUrl("jdbc:mysql://localhost:3306/my-db");
            ds.setUsername("root");
            ds.setPassword("");

            ds.setDriverClassName("org.mariadb.jdbc.Driver");

            ds.setInitialSize(3);
            ds.setMaxTotal(25);
            ds.setMinIdle(0);
            ds.setMaxIdle(8);
            ds.setMaxOpenPreparedStatements(100);

            dataSource = ds;
        }
        return dataSource;
    }

    public static void main(String [] args) throws Exception{   
       for(int i=0; i<11; i++){//spawn 11 threads & get each thread to process 600k sql rows at the same time
              new Thread("" + (i*600000)){

                public void run(){
                    System.out.println("Thread: " + getName() + " running");//prints correctly for all threads

                    Connection con = null;
                    PreparedStatement pstmt = null;
                    ResultSet rs = null;
                try {           
                    con = SandboxApp.getDataSource().getConnection();

                    pstmt = con.prepareStatement("select something from some_table limit "+getName()+",600000");
                    rs=pstmt.executeQuery();
                    while(rs.next()){  
                        System.out.println("Doing stuff for thread "+getName());//this only prints for getName() == 0
                            //give the other threads a turn...
                            try {
                                Thread.sleep(10);
                            }
                            catch(InterruptedException ex) {
                            }
                    }

                  } catch (Exception e) {
                    e.printStackTrace();
                  }finally{
                      try {pstmt.close();} catch (SQLException e) {}
                      try { con.close(); } catch(Exception e) {}
                      try { rs.close(); } catch(Exception e) {}
                  }
                }
              }.start();
        }
    }
}
答案

@ user207421是正确的,应该同步getDataSource()方法,当然我已经尝试过了;但是,这仍然不能解决我的线程“ 0”不让其他线程轮流使用的问题。

我从代码,所有其他库等中剥离了所有内容,直到我开始使用它,然后再次开始对其进行构建以找到断点。似乎主要决定因素是ResultSet的大小。我尝试在各个地方添加额外的thread.sleep时间,但是唯一有效的方法是分解查询以请求较小的ResultSet。

600k结果集,将只运行1个线程,1k结果集,将运行4个线程。对于仅包含100行的ResultSet,将运行所有11个线程。请注意,我在具有8GB内存分配给JVM的16 CPU系统上进行了测试(aws m5.4xlarge),因此硬件资源不应该成为一个重要因素。因此,我想我只需要将代码分成较小的块即可。

[当我最初调查此问题时,我惊讶地发现缺少针对该特定问题的特定代码示例(与ResultSet的大小和线程数无关),所以我只是在这里发布最终对我有用的为了获得完整的代码示例:

    import java.sql.*;
    import org.apache.commons.dbcp2.BasicDataSource;    

    public class SandboxApp {

        private static BasicDataSource dataSource;

        public static synchronized BasicDataSource getDataSource() {

            if (dataSource == null) {

                BasicDataSource ds = new BasicDataSource();

                ds.setUrl("jdbc:mysql://localhost:3306/my-db");
                ds.setUsername("root");
                ds.setPassword("");

                ds.setDriverClassName("org.mariadb.jdbc.Driver");

                ds.setInitialSize(3);
                ds.setMaxTotal(25);
                ds.setMinIdle(0);
                ds.setMaxIdle(8);
                ds.setMaxOpenPreparedStatements(100);

                dataSource = ds;
            }
            return dataSource;
        }

        public static void main(String [] args) throws Exception{   
           for(int i=0; i<11; i++){//spawn 11 threads & get each thread to process 100 sql rows at the same time
                  new Thread("" + (i*100)){

                    public void run(){
                        System.out.println("Thread: " + getName() + " running");

                        Connection con = null;
                        PreparedStatement pstmt = null;
                        ResultSet rs = null;
                    try {           
                        con = SandboxApp.getDataSource().getConnection();

                        pstmt = con.prepareStatement("select something from some_table limit "+getName()+",100");
                        rs=pstmt.executeQuery();
                        while(rs.next()){  
                            System.out.println("Doing stuff for thread "+getName());//With smaller ResultSet, this works fine for all 11 threads
                                //give the other threads a turn...
                                try {
                                    Thread.sleep(10);
                                }
                                catch(InterruptedException ex) {
                                }
                        }

                      } catch (Exception e) {
                        e.printStackTrace();
                      }finally{
                          try {pstmt.close();} catch (SQLException e) {}
                          try { con.close(); } catch(Exception e) {}
                          try { rs.close(); } catch(Exception e) {}
                      }
                    }
                  }.start();
            }
        }
    }

以上是关于java程序访问数据库,dbcp连接池,hibernate连接总是报池连接用光了/JDBC连接没有报错的主要内容,如果未能解决你的问题,请参考以下文章

java dbcp2多线程连接访问

DBCP数据库连接池的简单使用

DBCP数据库连接池的简单使用

Java学习:数据库连接池DBCP的使用

DBCP(Apache Commons 数据库连接池)是不是仍然相关?

Java第三方数据库连接池库-DBCP-C3P0-Tomcat内置连接池