必威体育Betway必威体育官网
当前位置:首页 > IT技术

连接池(原生+常用)

时间:2019-10-04 00:15:32来源:IT技术作者:seo实验室小编阅读:59次「手机版」
 

连接池

连接池

涉及概念:设计模式:资源池(Resource Pool)百度一下,你就知道

数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,从“缓冲池”中取出一个,使用完毕之后再放回去。

Tomcat连接池

Tomcat默认使用的是DBCP数据库连接池,使用的tomcat-dbcp.jar包。

数据源可以给项目单独配置,也可以全局配置:

单独配置:在项目META-INF下新建context.xml,内容如下Resource

全局设置:在tomcat中conf目录下的context.xml文件 context节点下添加resource

<Resource name="jdbc/Mobile"

auth="Container"

type="javax.sql.datasource"

factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"

testwhileIdle="true"

testOnBorrow="true"

testOnReturn="false"

validationQuery="SELECT 1"

validationInterval="30000"

timeBetweenEvictionRunsMillis="30000"

maxActive="100"

Minidle="10"

maxWait="10000"

initialSize="10"

removeAbandonedTimeout="60"

removeAbandoned="true"

logAbandoned="false"

minEvictableIdleTimeMillis="30000"

jmxEnabled="true"

fairqueue="true"

jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;

   org.apache.tomcat.jdbc.pool.interceptor.statementfinalizer"

username="root"

password='root'

driverClassName="com.mysql.jdbc.Driver"

url="jdbc:mysql://127.0.0.1:3306/hsdb?useunicode=true&characterEncoding=utf-8&autoReconnect=true"/>

Spring框架常用的连接池C3P0

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定。c3p0所需jar:c3p0-0.9.2.1.jar mchange-commons-java-0.2.3.4.jar

基本使用:

1.引入jar包

2.编写配置文件

default-config:

   <?xml version="1.0" encoding="UTF-8"?>

<c3p0-config>

   <default-config>

       <property name="user">root</property>

       <property name="password">root</property>

       <property name="driverClass">com.mysql.jdbc.Driver</property>

       <property name="jdbcUrl">

           jdbc:mysql://localhost:3306/dbname?useSSL=true

       </property>

       <!--以上的user是数据库的用户,password是数据库的密码,driverClass是mysql的数据库驱动,jdbcUrl是连接数据库的url -->

       <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 -->

       <property name="acquireincrement">5</property>

       <!--初始化时获取十个连接,取值应在minPoolSize与maxPoolSize之间 -->

       <property name="initialPoolSize">10</property>

       <!--连接池中保留的最小连接数 -->

       <property name="minPoolSize">10</property>

       <!--连接池中保留的最大连接数 -->

       <property name="maxPoolSize">50</property>

       <property name="maxStatements">20</property>

       <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->

       <property name="maxStatementsPerConnection">5</property>

   </default-config>

   <named-config name="mysql">

       <property name="user">root</property>

       <property name="password">root</property>

       <property name="driverClass">com.mysql.jdbc.Driver</property>

       <property name="jdbcUrl">jdbc:mysql://localhost:3306/dbname?useSSL=true</property>

       <property name="acquireIncrement">5</property>

       <property name="initialPoolSize">10</property>

       <property name="minPoolSize">10</property>

       <property name="maxPoolSize">50</property>

       <property name="maxStatements">20</property>

       <property name="maxStatementsPerConnection">5</property>

   </named-config>

</c3p0-config>

3.实现操作

  C3P0中连接池的实现类名CombopooledDataSource 加载配置文件可以加载默认配置也可以加载带名字的配置

      ComboPooledDataSource dataSource = new ComboPooledDataSource();

//加载有名称的配置named-config

//ComboPooledDataSource dataSource =

              new ComboPooledDataSource("mysql");

  在Spring中的使用:

  <!-- 配置c3p0数据源 -->

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">

<property name="jdbcUrl" value="${jdbc.url}" />

<property name="driverClass" value="${jdbc.driverClassName}" />

<property name="user" value="${jdbc.username}" />

<property name="password" value="${jdbc.password}" />

<!--连接池中保留的最大连接数。Default: 15 -->

<property name="maxPoolSize" value="100" />

<!--连接池中保留的最小连接数。-->

<property name="minPoolSize" value="1" />

<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->

<property name="initialPoolSize" value="10" />

<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->

<property name="maxIdleTime" value="30" />

<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->

<property name="acquireIncrement" value="5" />

<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->

<property name="maxStatements" value="0" />

<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->

<property name="idleConnectionTestPeriod" value="60" />

<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->

<property name="acquireretryAttempts" value="30" />

<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。Default: false-->

<property name="breakAfterAcquireFailure" value="true" />

<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable等方法来提升连接测试的性能。Default: false -->

<property name="testConnectionOnCheckout"  value="false" />  

</bean>

JDBC连接池的一种原生写法:

Jdbc.properties

driver=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/dbname?useSSL=true

username=root

password=root

jdbcPoolInitSize=10

JdbcPool.java

package com.test0815;

import java.io.InputStream;

import java.io.printwriter;

import java.lang.reflect.Invocationhandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.SQLFeatureNotSupportedException;

import java.util.LinkedList;

import java.util.Properties;

import java.util.logging.Logger;

import javax.sql.DataSource;

/**

* 简单的的jdbc连接池实现

*/

public class JdbcPool implements DataSource {

   /**

* 由于要频繁读写List集合,所以这里使用LinkedList存储数据库连接比较合适

* ps:LinkedList在性能上插入、删除数据速度快。

*/

   private static LinkedList<Connection> listConnections = new LinkedList<Connection>();

   private static Connection conn;

   // 在静态代码块中加载jdbc.properties数据库配置文件

   static {

   InputStream in = JdbcPool.class.getResourceAsStream("/jdbc.properties");

   Properties prop = new Properties();

   try {

   prop.load(in);

   String driver = prop.getProperty("driver");

   String url = prop.getProperty("url");

   String username = prop.getProperty("username");

   String password = prop.getProperty("password");

   // 数据库连接池的初始化连接数大小

   int jdbcPoolInitSize = integer.parseInt(prop

       .getProperty("jdbcPoolInitSize"));

   // 加载数据库驱动

   class.forname(driver);

   for (int i = 0; i < jdbcPoolInitSize; i++) {

   conn = DriverManager.getConnection(url, username, password);

           // System.out.println("获取到了连接" + conn);

   // 将获取到的数据库连接加入到listConnections集合中,listConnections集合此时就是一个存放了数据库连接的连接池

   listConnections.add(conn);

   }

   } catch (Exception e) {

   throw new ExceptionInInitializerERROR(e);

   }

   }

   /*

*

* 获取数据库连接

*/

   @Override

   public Connection getConnection() throws SQLException {

   // 如果数据库连接池中的连接对象的个数大于0

   if (listConnections.size() > 0) {

   // 从listConnections集合中获取一个数据库连接

   System.out.println("listConnections数据库连接池大小是:"

       + listConnections.size());

   // 返回Connection对象的代理对象

   return (Connection) Proxy.newProxyinstance(JdbcPool.class

       .getClassLoader(), conn.getClass().getInterfaces(),

       new InvocationHandler() {

           @Override

           public Object invoke(Object proxy, Method method,

                   Object[] args) throws throwable {

               if (!method.getName().equals("close")) {

                   System.out.println("获取到连接池连接对象......" + conn);

                   return method.invoke(conn, args);

               } else {

                   // 如果调用的是Connection对象的close方法,就把conn还给数据库连接池

                   listConnections.add(conn);

                   // System.out.println(conn+ ",还给数据库连接池了");

                   // System.out.println("listConnections数据库连接池大小为"+

                   // listConnections.size());

                   return null;

               }

           }

       });

   } else {

          throw new runtimeexception("对不起,数据库忙");

   }

   }

  

   //Override方法

   @Override

   public PrintWriter getLogWriter() throws SQLException {

   return null;

   }

   @Override

   public int getLoginTimeout() throws SQLException {

   return 0;

   }

   @Override

   public Logger getparentLogger() throws SQLFeatureNotSupportedException {

   return null;

   }

   @Override

   public void setLogWriter(PrintWriter out) throws SQLException {

  

   }

   @Override

   public void setLoginTimeout(int seconds) throws SQLException {

  

   }

   @Override

   public boolean isWrAPPerFor(Class<?> iface) throws SQLException {

   return false;

   }

   @Override

   public <T> T unwrap(Class<T> iface) throws SQLException {

   return null;

   }

   @Override

   public Connection getConnection(String username, String password)

   throws SQLException {

   return null;

   }

}

JDBCUtil.java

package com.test0815;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

public class JDBCUtil {

   private static JdbcPool pool = new JdbcPool();

   /**

* 获取资源

*/

   public static Connection getConnection() throws SQLException {

   return pool.getConnection();

   }

   /**

* 关闭资源

*/

   public static void close(ResultSet resultSet, Statement statement,

   Connection connection) {

   if (resultSet != null) {

   try {

       resultSet.close();

   } catch (SQLException e) {

       throw new RuntimeException(e);

   }

   resultSet = null;

   }

   if (statement != null) {

   try {

       statement.close();

   } catch (SQLException e) {

       throw new RuntimeException(e);

   }

   statement=null;

   }

   if (connection != null) {

   try {

       connection.close();

   } catch (SQLException e) {

       throw new RuntimeException(e);

   }

   connection = null;

   }

   }

  

   //插入数据操作

   public static void insertOrDeleteOrUpdate(String sql) {

   try {

   Connection connection = JDBCUtil.getConnection();

   PreparedStatement pst = connection.preparestatement(sql);

   int execute = pst.executeUpdate();

   System.out.println("执行语句:" + sql + "," + execute + "行数据受影响");

   JDBCUtil.close(null, pst, connection);

   } catch (SQLException e) {

   System.out.println("异常提醒:" + e);

   }

   }

  

   //插入数据操作

   public static List<Map<String, Object>> select(String sql) {

   List<Map<String, Object>> returnResultToList = null;

   try {

   Connection connection = JDBCUtil.getConnection();

   PreparedStatement pst = connection.prepareStatement(sql);

   ResultSet resultSet = pst.executequery();

   returnResultToList = returnResultToList(resultSet);

   JDBCUtil.close(resultSet, pst, connection);

   } catch (SQLException e) {

   System.out.println("异常提醒:" + e);

      }

   return returnResultToList;

   }

   /**

*

* 数据返回集合

* @param resultSet

* @return

* @throws SQLException

*/

   public static List<Map<String, Object>> returnResultToList(

   ResultSet resultSet) {

   List<Map<String, Object>> values = null;

   try {

   // 键: 存放列的别名, 值: 存放列的值.

   values = new ArrayList<>();

   // 存放字段名

   List<String> columnName = new ArrayList<>();

   ResultSetMetaData rsmd = resultSet.getMetaData();

   for (int i = 0; i < rsmd.getColumnCount(); i++) {

   // 字段名

   columnName.add(rsmd.getColumnLabel(i + 1));

   }

   System.out.println("表字段为:");

   System.out.println(columnName);

   System.out.println("表数据为:");

   Map<String, Object> map = null;

   // 处理 ResultSet, 使用 while 循环

   while (resultSet.next()) {

   map = new HashMap<>();

   for (String column : columnName) {

       Object value = resultSet.getObject(column);

       map.put(column, value);

       System.out.print(value + "\t");

   }

   // 把一条记录的 Map 对象放入准备的 List 中

   values.add(map);

   System.out.println();

   }

   } catch (SQLException e) {

   System.out.println("异常提醒:" + e);

   }

   return values;

   }

}

相关阅读

vi vim 常用命令

命令行模式 从命令行切换到编辑模式,i、a、o i 为从目前光标所在处输入, I 为在目前所在行的第一个非空格符处开始输入。  a 为从

[Excel常用函数] sumif & sumifs函数

sumif函数 sumif函数是用来根据指定条件对若干单元格进行求和 sumif函数的语法格式 =sumif(range,criteria,sum_range) Sumif(条件

VIM系列-1-常用命令集锦

话说笔者早就想对这方面来个“大扫除”拉。学习有多种方式,你可以零碎的学习,也可以系统的学习。因为命令很琐碎,如果每次用的时候再

数学建模常用模型05 :多元回归模型

1 基本知识介绍 1.1回归模型的引入 由于客观事物内部规律的复杂性及人们认识程度的限制,无法分析实际对象内在的因果关系,建立合乎

进入注册表一些常用的命令大全汇总

进入注册表一些常用的命令大全汇总 进入注册表有很多的命令.如果很熟悉了.使用起来也很方便的我们可以点击桌面左下角的开始>>运

分享到:

栏目导航

推荐阅读

热门阅读