7-连接池

自定义连接池

        用户每次请求都需要向数据库获得连接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。

         Java为连接池实现提供了一个规范(接口),规范的写法,即实现DataSource接口

public class MyPool implements DataSource {
    private static List<Connection> connections;
    private static String driverClass;
    private static String url;
    private static String user;
    private static String password;
    static {
        connections = Collections.synchronizedList(new LinkedList<>());
        try {
            //加载属性文件
            InputStream is= MyPool.class.getClassLoader().getResourceAsStream("db.properties");
            //创建集合
            Properties properties=new Properties();
            //从流中加载
            properties.load(is);
            //赋值
            driverClass=properties.getProperty("driverClass");
            url=properties.getProperty("url");
            user=properties.getProperty("user");
            password=properties.getProperty("password");
            //注册驱动
            Class.forName(driverClass);

            //初始化元素
            for (int i = 0; i < 5; i++) {
                connections.add(DriverManager.getConnection(url, user, password));
            }
            System.out.println("连接池初始化完成");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Connection getConnection() throws SQLException {
        synchronized (connections){
            if(connections.size()>0){
                Connection connection = connections.remove(0);
                System.out.println("使用了"+connection.toString());
                return connection;
            }
        }
        return null;
    }
    //释放链接
    public void release(Connection conn){
        System.out.println("归还了:"+conn.toString());
        connections.add(conn);
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }
    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }
    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }
    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }
    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }
    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }
    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

DBCP连接池

        DBCP(DataBase connection pool),[数据库连接池]。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要2个包:commons-dbcp.jar,commons-pool.jar。由于建立数据库连接是一个非常耗时的行为,所以通过连接池预先同数据库建立一些连接放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。

  • 相应jar包 :

        mysql驱动包,commons-dbcp.jar,commons-pool.jar,commons-logging.jar (日志支持)

  • 硬编码使用DBCP:

        所谓的硬编码方式就是在代码中添加配置。

public class DbUtils_DBCP {
    private static BasicDataSource basicDataSource;

    static {
        //1.方式一:使用设置属性
        basicDataSource = new BasicDataSource();

        //1.1设置四个基本属性
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUrl("jdbc:mysql://localhost:3306/test");
        basicDataSource.setUsername("root");
        basicDataSource.setPassword("");

        //1.2设置其他属性
        //初始大小
        basicDataSource.setInitialSize(10);
        //最大大小
        basicDataSource.setMaxTotal(50);
        //最大空闲
        basicDataSource.setMaxIdle(30);
        //最小空闲
        basicDataSource.setMinIdle(5);
        //超时时间
        basicDataSource.setMaxWaitMillis(5000);
    }

    //2.获取连接
    public static Connection getConnection(){
        try {
            return basicDataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    //3.释放资源
    public static void closeAll(Connection conn, Statement stat, ResultSet rs){
        try {
            if (rs != null) {
                rs.close();
            }
            if (stat != null) {
                stat.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
    public static void main(String[] args) throws Exception{
        for (int i = 0; i < 50; i++) {
            Connection conn = DbUtils_DBCP.getConnection();
            System.out.println(conn.toString());
            conn.close();//并不会真正关闭连接,而是把对象放回连接池中
        }
    }

        运行结果:

        JDBC原始连接:

  • 软编码使用DBCP:

        所谓的软编码,就是在项目中添加配置文件,这样就不需要每次代码中添加配置!

        文件名称:dbcp.properties       文件位置:src下

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxTotal=50
#<!-- 最大空闲连接 -->
maxIdle=30
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWaitMillis=5000
    private static BasicDataSource basicDataSource;

    static {
        //2.方式二:使用配置文件
        try {
            Properties properties = new Properties();
            InputStream is = Demo1.class.getClassLoader().getResourceAsStream("dbcp.properties");
            //properties.load(new FileInputStream("src/info.properties"));
            properties.load(is);
            basicDataSource = BasicDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("连接池初始化失败");
        }
    }

C3P0连接池

        C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。

        相应 jar 包:mysql驱动包、c3p0-0.9.1.2.jar、mchange-commons-java-0.2.11.jar

c3p0与dbcp区别:
1、dbcp没有自动回收空闲连接的功能,c3p0有自动回收空闲连接功能
2、dbcp需要手动加载配置文件,c3p0自动加载
  • 硬编码使用C3P0:
    private static ComboPooledDataSource dataSource;
    static {
        try {
            dataSource = new ComboPooledDataSource();
            //四个基本属性
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
            dataSource.setUser("root");
            dataSource.setPassword("");
            //其他属性
            dataSource.setMaxPoolSize(50);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

        运行结果:

  • 软编码使用c3p0:

        c3p0是在外部添加配置文件,工具直接进行应用,因为直接引用,所以要求固定的命名和文件位置

        文件位置:src           文件命名:c3p0-config.xml   /   c3p0.properties

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!-- 默认配置,如果没有指定则使用这个配置 -->
    <default-config>
        <!-- 基本配置 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
        <property name="user">root</property>
        <property name="password"></property>
        <!--扩展配置-->
        <!-- 连接超过5秒报错-->
        <property name="checkoutTimeout">5000</property>
        <!--20秒检查空闲连接 -->
        <property name="idleConnectionTestPeriod">20</property>
        <!-- 初始大小 -->
        <property name="initialPoolSize">10</property>
        <!-- 每次增长的个数 -->
        <property name="acquireIncrement">5</property>
        <!-- 30秒不适用丢弃-->
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">50</property>
        <property name="minPoolSize">10</property>
    </default-config>
    <!-- 命名的配置 -->
    <named-config name="mysql">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/mysql</property>
        <property name="user">root</property>
        <property name="password"></property>
        <!-- 如果池中数据连接不够时一次增长多少个 -->
        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">10</property>
        <property name="maxPoolSize">50</property>
    </named-config>
</c3p0-config>

        XML 优先级高于 properties,XML 可以配置多个,properties 只可配置一个

c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/test
c3p0.user=root
c3p0.password=
c3p0.acquireIncrement=5
c3p0.initialPoolSize=10
c3p0.minPoolSize=10
c3p0.maxPoolSize=50
  • Tips:
//1:c3p0的配置文件内部可以包含命名配置文件和默认配置文件,默认是选择默认配置,
//如果需要切换命名配置可以在创建c3p0连接池的时候填入命名即可。
public ComboPooledDataSource(String configName) {super(configName);}

//2:如果xml配置文件和属性文件都存在时,xml优先级高于属性文件
public class TestC3p0 {
	public static void main(String[] args) throws Exception {
      	//创建ComboPooledDataSource对象使用默认配置
		ComboPooledDataSource  dataSource = new ComboPooledDataSource();
		
		Connection connection = dataSource.getConnection();
		Statement createStatement = connection.createStatement();
		String sql = "select * from student;";
		ResultSet resultSet = createStatement.executeQuery(sql);
		while (resultSet.next()) {
			System.out.println(resultSet.getString(1));
		}
		resultSet.close();
      	createStatement.close();
      	connection.close();
    }	
}

Druid连接池

Druid 是目前比较流行的高性能的,分布式列存储的OLAP框架(具体来说是MOLAP)。它有如下几个特点:
一.亚秒级查询
     druid提供了快速的聚合能力以及亚秒级的OLAP查询能力,多租户的设计,是面向用户分析应用的理想方式。
二.实时数据注入
     druid支持流数据的注入,并提供了数据的事件驱动,保证在实时和离线环境下事件的实效性和统一性
三.可扩展的PB级存储
     druid集群可以很方便的扩容到PB的数据量,每秒百万级别的数据注入。即便在加大数据规模的情况下,也能保证其时效性
四.多环境部署
     druid既可以运行在商业的硬件上,也可以运行在云上。它可以从多种数据系统中注入数据,包括hadoop,spark,kafka,storm和samza等
五.丰富的社区
     druid拥有丰富的社区,供大家学习

        相关 jar 包:druid-1.1.5.jar 

  •   硬编码使用druid:
    //声明连接池对象
    private static DruidDataSource dataSource;
    static{
        dataSource = new DruidDataSource();

        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUsername("root");
        dataSource.setPassword("");

        //初始大小
        dataSource.setInitialSize(10);
        //最大大小
        dataSource.setMaxActive(50);
        //最大空闲
        dataSource.setMaxIdle(30);
        //最小空闲
        dataSource.setMinIdle(5);
        //超时时间
        dataSource.setMaxWait(5000);
    public static void main(String[] args) throws Exception{
        for (int i = 0; i < 50; i++) {
            Connection conn = DbUtils_Druid.getConnection();
            System.out.println(conn.toString());
//            conn.close();//没有自动回收空闲连接功能
        }
    }

        运行结果:

  • 软编码使用druid:

        druid.properties:

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=5000
    //声明连接池对象
    private static DruidDataSource dataSource;
    static{
        //实例化配置对象
        Properties properties=new Properties();
        try {
            //加载配置文件内容
            properties.load(DbUtils_Druid.class.getClassLoader().getResourceAsStream("druid.properties"));
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值