movie电影网bug小结

电影网bug小结

问题描述:

​ 使用C3P0连接了MYSQL数据库之后,访问页面会疯狂创建新的connection对象,然后系统就崩溃了(超过最大连接池数量)

​ C3P0修改后的DBUtil:

public Connection getConn() throws Exception{
    DataSource ds=new ComboPooledDataSource("moviec3p0");
    conn=ds.getConnection();
    System.out.println(conn);
    return conn;
}

解决方案:

在DBUtil的其他方法中,每次使用conn连接之前,都给conn创建了新的连接,修改即可;

​ 以上方法行不通,原因是我的代码不是单例模式,每次使用DBUtil都会创建新的对象,所以就会一直创建连接;新的解决方案应该是,修改C3P0的配置文件,让空闲的连接释放!

​ 2022年6月16日08:20:51:补充:

​ 虽然大体上顺畅了,但是到了访问多的时候还是会卡住;

一、在mysql数据库的my.ini文件中添加
允许最大连接数:
max_connections=1000
二、在c3p0的xml文件中添加如下配置如图:

image-20220614172510890

1.breakAfterAcquireFailure=false,为true会导致连接池占满后不提供服务。所以必须为false
2.acquireRetryAttempts=10,获取连接失败时重试10次,默认重试30次,减少重试次数。
3.idleConnectionTestPeriod=30,每30秒检查一次空闲连接,加快释放连接。
4.maxIdleTime=10,连接10秒内不使用则释放连接,加快连接释放。
5.checkoutTimeout=10000,获取连接超时时间为10秒,默认则无限等待。设置此值高并发时(连接数占满)可能会引发中断数据库操作风险。
6.unreturnedConnectionTimeout=20,连接回收超时时间,设置比maxIdleTime大
7.debugUnreturnedConnectionStackTraces=true,连接泄漏时打印堆栈信息


版权声明:本文为CSDN博主「Victory233」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43380128/article/details/102573005

c3p0-config.xml 内容:

<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>
  	<!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/test?characterEncoding=utf-8</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 连接池参数 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">10</property>
    <property name="checkoutTimeout">3000</property>
    <property name="acquireIncrement">3</property>
  </default-config>

  <named-config name="otherc3p0"> 
    <!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/hrm?characterEncoding=utf-8</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 连接池参数 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">10</property>
    <property name="checkoutTimeout">10000</property>
    <property name="acquireIncrement">3</property>
    <property name="breakAfterAcquireFailure">false</property>	<!-- 为true会导致连接池占满后不提供服务。所以必须为false -->
    <property name="acquireRetryAttempts">10</property>	<!-- 获取连接失败时重试10次,默认重试30次,减少重试次数。 -->
    <property name="idleConnectionTestPeriod">30</property>	<!-- 每30秒检查一次空闲连接,加快释放连接。 -->
    <property name="maxIdleTime">10</property>	<!-- 连接10秒内不使用则释放连接,加快连接释放。 -->
    <property name="unreturnedConnectionTimeout">20</property>	<!-- 连接回收超时时间,设置比maxIdleTime大 -->
    <property name="debugUnreturnedConnectionStackTraces">true</property>	<!-- 连接泄漏时打印堆栈信息 -->
  </named-config>
  
</c3p0-config>

此外,我还看到了另外一片博主的解决方案,他使用了单利模式,这里可以记录学习:

使用C3P0整合JDBC

数据库配置:

#Oracle Config
#jdbc.driver=oracle.jdbc.driver.OracleDriver
#jdbc.url=jdbc:oracle:thin:@localhost:1521:ora9i
#jdbc.username=qq
#jdbc.pwd=qq

#MySQL Config
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=jdbctest
jdbc.pwd=123456

DBUtils,初始化连接池配置,设置数据库的最大连接数和最小连接数

package hn.veryedu.jdbc.common.db;

import java.io.FileInputStream;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.DataSources;

public class DBUtils {
    
    private static String url = null;
    
    private static String username = null;
    
    private static String pwd = null;
    
    private static DataSource ds_pooled;
    /** 
     *  加载数据库连接的配置文件和驱动
     */
    static{
        FileInputStream fis = null;
        
        Properties env = new Properties();
        try {
            fis = new FileInputStream("dbconfig.properties");
            //加载属性文件中的数据库配置信息
            //以=左边作为key值,右边作为value值
            env.load(fis); 
            
            //1. 加载驱动类
            Class.forName(env.getProperty("jdbc.driver"));
            
            url = env.getProperty("jdbc.url");
            username = env.getProperty("jdbc.username");
            pwd = env.getProperty("jdbc.pwd");
            
            //设置连接数据库的配置信息
            DataSource ds_unpooled = DataSources
                    .unpooledDataSource(url, username, pwd);
            
            
            
            Map<String, Object> pool_conf = new HashMap<String, Object>();
            //设置最大连接数
            pool_conf.put("maxPoolSize", 20);
            //连接池应该保有的最小连接的数量
            pool_conf.put("minPoolSize", 2);
            //初始化连接池时,获取的连接个数
            pool_conf.put("initialPoolSize", 10);
            //当连接池中已经没有连接时,连接池自动获取连接时一次获取的连接个数
            pool_conf.put("acquireIncrement", 3);
            ds_pooled = DataSources.pooledDataSource(ds_unpooled,
                    pool_conf);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    /**
     *  获取连接对象
     */
    public static Connection getConnection()  {
        // 2. 设置连接的url,username,pwd
        Connection connection = null;
        try {
            connection = ds_pooled.getConnection();
            //connection.prepareStatement("set names utf8mb4").executeQuery();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return connection;
    }
    
    /**
     * 释放连接池资源
     */
    public static void clearup(){
        if(ds_pooled != null){
            try {
                DataSources.destroy(ds_pooled);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    /**
     * 资源关闭
     * 
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void close(ResultSet rs, Statement stmt
            , Connection conn) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

然后是JdbcUtils查询各种数据List、Map等,通过DBUtils获取数据库连接,使用完成之后释放所有的连接:

package hn.veryedu.jdbc.common.db;

import java.lang.reflect.Field;  
import java.sql.Connection;   
import java.sql.PreparedStatement;  
import java.sql.ResultSet;  
import java.sql.ResultSetMetaData;  
import java.sql.SQLException;  
import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  
  
  
  
public class JdbcUtils {  
    private Connection connection;
    private PreparedStatement pstmt;
    private ResultSet resultSet;
    
      
    /** 
     * 获得数据库的连接 
     * @return 
     * @throws SQLException 
     */  
    public Connection getConnection() throws SQLException{  
        connection = DBUtils.getConnection(); 
        //如果数据库支持utf8mb4 建立连接后需要使用下面的代码
        //connection.prepareStatement("set names utf8mb4").executeQuery();
        return connection;  
    } 
    
      
      
      
    /** 
     * 增加、删除、改 
     * @param sql 
     * @param params 
     * @return 
     * @throws SQLException 
     */  
    public boolean updateByPreparedStatement(String sql, List<Object> params)throws SQLException{
        boolean flag = false;
        int result = -1;
        this.getConnection();
        pstmt = connection.prepareStatement(sql);
        int index = 1;
        if(params != null && !params.isEmpty()){
            for(int i=0; i<params.size(); i++){
                pstmt.setObject(index++, params.get(i));
            }
        }
        result = pstmt.executeUpdate();
        flag = result > 0 ? true : false;
        this.releaseConn();
        return flag;  
    }
  
    /** 
     * 查询单条记录 
     * @param sql 
     * @param params 
     * @return 
     * @throws SQLException 
     */  
    public Map<String, Object> findSimpleResult(String sql, List<Object> params) throws SQLException{  
        Map<String, Object> map = new HashMap<String, Object>();  
        int index  = 1;
        this.getConnection();
        pstmt = connection.prepareStatement(sql);  
        if(params != null && !params.isEmpty()){  
            for(int i=0; i<params.size(); i++){  
                pstmt.setObject(index++, params.get(i));  
            }  
        }  
        resultSet = pstmt.executeQuery();//返回查询结果  
        ResultSetMetaData metaData = resultSet.getMetaData();  
        int col_len = metaData.getColumnCount();  
        while(resultSet.next()){  
            for(int i=0; i<col_len; i++ ){  
                String cols_name = metaData.getColumnName(i+1);  
                Object cols_value = resultSet.getObject(cols_name);  
                if(cols_value == null){  
                    cols_value = "";  
                }  
                map.put(cols_name, cols_value);  
            }  
        }  
        this.releaseConn();
        return map;  
    }  
  
    /**
     * 查询多条记录 
     * @param sql 
     * @param params 
     * @return 
     * @throws SQLException 
     */  
    public List<Map<String, Object>> findModeResult(String sql, List<Object> params) throws SQLException{  
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();  
        int index = 1; 
        this.getConnection();
        pstmt = connection.prepareStatement(sql);  
        if(params != null && !params.isEmpty()){  
            for(int i = 0; i<params.size(); i++){  
                pstmt.setObject(index++, params.get(i));  
            }  
        }  
        resultSet = pstmt.executeQuery();  
        ResultSetMetaData metaData = resultSet.getMetaData();  
        int cols_len = metaData.getColumnCount();  
        while(resultSet.next()){  
            Map<String, Object> map = new HashMap<String, Object>();  
            for(int i=0; i<cols_len; i++){  
                String cols_name = metaData.getColumnName(i+1);  
                Object cols_value = resultSet.getObject(cols_name);  
                if(cols_value == null){  
                    cols_value = "";  
                }  
                map.put(cols_name, cols_value);  
            }  
            list.add(map);  
        }
        this.releaseConn();
        return list;  
    }  
  
    /**
     * 通过反射机制查询单条记录 
     * @param sql 
     * @param params 
     * @param cls 
     * @return 
     * @throws Exception 
     */  
    public <T> T findSimpleRefResult(String sql, List<Object> params,  
            Class<T> cls )throws Exception{  
        T resultObject = null;  
        int index = 1;
        this.getConnection();
        pstmt = connection.prepareStatement(sql);  
        if(params != null && !params.isEmpty()){  
            for(int i = 0; i<params.size(); i++){  
                pstmt.setObject(index++, params.get(i));  
            }  
        }  
        resultSet = pstmt.executeQuery();  
        ResultSetMetaData metaData  = resultSet.getMetaData();  
        int cols_len = metaData.getColumnCount();  
        while(resultSet.next()){  
            //通过反射机制创建一个实例  
            resultObject = cls.newInstance();  
            for(int i = 0; i<cols_len; i++){  
                String cols_name = metaData.getColumnName(i+1);  
                Object cols_value = resultSet.getObject(cols_name);  
                if(cols_value == null){  
                    cols_value = "";  
                }  
                Field field = cls.getDeclaredField(cols_name);  
                field.setAccessible(true); //打开javabean的访问权限  
                field.set(resultObject, cols_value);  
            }  
        } 
        this.releaseConn();
        return resultObject;  
    }  
  
    /**
     * 通过反射机制查询多条记录 
     * @param sql  
     * @param params 
     * @param cls 
     * @return 
     * @throws Exception 
     */  
    public <T> List<T> findMoreRefResult(String sql, List<Object> params,  
            Class<T> cls )throws Exception {  
        List<T> list = new ArrayList<T>();  
        int index = 1; 
        this.getConnection();
        pstmt = connection.prepareStatement(sql);  
        if(params != null && !params.isEmpty()){  
            for(int i = 0; i<params.size(); i++){  
                pstmt.setObject(index++, params.get(i));  
            }  
        }  
        resultSet = pstmt.executeQuery();  
        ResultSetMetaData metaData  = resultSet.getMetaData();  
        int cols_len = metaData.getColumnCount();  
        while(resultSet.next()){  
            //通过反射机制创建一个实例  
            T resultObject = cls.newInstance();  
            for(int i = 0; i<cols_len; i++){  
                String cols_name = metaData.getColumnName(i+1);  
                Object cols_value = resultSet.getObject(cols_name);  
                if(cols_value == null){  
                    cols_value = "";  
                }  
                Field field = cls.getDeclaredField(cols_name);  
                field.setAccessible(true); //打开javabean的访问权限  
                field.set(resultObject, cols_value);  
            }  
            list.add(resultObject);  
        } 
        this.releaseConn();
        return list;  
    }  
  
    /** 
     * 返回单个结果值,如count\min\max等 
     *  
     * @param sql 
     *            sql语句 
     * @param paramters 
     *            参数列表 
     * @return 结果 
     * @throws SQLException 
     */  
    public  Integer queryForInt(String sql, Object... paramters)  
            throws SQLException {  
        Integer result = null;  
        
        try {  
            this.getConnection();
            pstmt = connection.prepareStatement(sql);  
   
            for (int i = 0; i < paramters.length; i++) {  
                pstmt.setObject(i + 1, paramters[i]); 
            }  
            resultSet = pstmt.executeQuery(); 
            
            ResultSetMetaData metaData = resultSet.getMetaData();  
            while(resultSet.next()){  
                String cols_name = metaData.getColumnName(0+1);  
                Object cols_value = resultSet.getObject(cols_name);  
                result = Integer.valueOf(cols_value.toString());
            } 
            return result;  
        } catch (SQLException e) {  
            throw new SQLException(e);  
        } finally {  
            releaseConn(); 
        }  
    } 
    
    /** 
     * 释放数据库连接 
     */  
    public void releaseConn(){  
        DBUtils.close(resultSet, pstmt, connection);  
    }  
  
}

测试类TestMySQLConnection:

package hn.veryedu.jdbc.mysql;

import hn.veryedu.jdbc.common.db.DBUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;



public class TestMySQLConnection {
    private static Integer counter = 0;

    public static void main(String[] args){
        
        for (int i = 1; i <= 2000; i++) {
            new Thread(new Runnable() {
                public void run() {
                    Connection conn = null;
                    PreparedStatement pstmt= null;
                    ResultSet resultSet= null;
                    try {
                        conn = DBUtils.getConnection();
                        synchronized (counter) {
                            System.out.print(Thread.currentThread().getName());
                            System.out.print("    counter = " + counter++
                                    + "  conn = " + conn);
                            System.out.println();
                            
                            pstmt = conn.prepareStatement("select * from user_t");
                            resultSet = pstmt.executeQuery(); 
                            ResultSetMetaData metaData = resultSet.getMetaData();  
                            int cols_len = metaData.getColumnCount();  
                            while(resultSet.next()){  
                                for(int i=0; i<cols_len; i++){  
                                    String cols_name = metaData.getColumnName(i+1);  
                                    Object cols_value = resultSet.getObject(cols_name);  
                                    //System.out.println(cols_name+"---"+cols_value); 
                                }  
                            }
                            DBUtils.close(resultSet, pstmt, conn);
                            //conn.close();
                        }
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }  
                }
            }).start();
        }
    }
}

测试类TestJdcb

package hn.veryedu.jdbc.mysql;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import hn.veryedu.jdbc.common.db.JdbcUtils;

public class TestJdcb {

    /**
     * @param args
     * @throws SQLException 
     */
    public static void main(String[] args) throws SQLException {
        // TODO Auto-generated method stub
        for (int i = 1; i <= 20; i++){
            JdbcUtils jdbc = new JdbcUtils();
            String sql = "select * from user_t";
            List<Map<String, Object>> list = jdbc.findModeResult(sql, null);
            for (int j = 0; j < list.size(); j++) {
                System.out.println(list.get(j));
            }
        }
    }

}

转载于:https://www.cnblogs.com/jiafuwei/p/6552823.html

posted @ 2022-06-21 23:50  devynlime  阅读(128)  评论(0编辑  收藏  举报