JDBC学习(八)数据库连接池

什么是数据库连接池,为什么用连接池?

数据库连接池就是保存若干个Connection对象一个连接池对象。使用池来管理,可以重复使用Connection。有了池,可以不用自己来创建连接。直接通过池对象获取,用完后,调用Connecition的close()方法,将Connection对象返还给池。

JDBC数据库连接池接口

Java中并没有实现连接池,但是规定了所有三方实现的连接池必须实现java.sql.DataSource接口。DataSource接口中定义了两个重载的getConnection方法:

  • Connection getConnection()
  • Connection getConnection(String username, String password)

连接池参数

初始大小:初始创建多少个Connection对象

最小空闲连接数:低于这个数量,就新建连接对象

增量:一次创建的最小单位

最大空闲连接数:超过这个数量,就关闭多余的连接对象

最大的连接数:超出数量,就需要进行等待

下面介绍两个连接池

BDCP

DBCP是Apache提供的一款开源免费的数据库连接池。

使用前需要导入连个jar包

  • commons-dbcp-xx.jar
  • commons-pool-xx.jar

代码

@Test
    public void func() throws SQLException {
        //建立连接池对象
        BasicDataSource bd=new BasicDataSource();

        //设置四大参数
        bd.setDriverClassName("com.mysql.jdbc.Driver");
        bd.setUrl("jdbc:mysql://localhost:3306/sql_test");
        bd.setUsername("root");
        bd.setPassword("123456");

        //设置池参数
        bd.setMaxActive(20);//最大连接数
        bd.setMinIdle(3);//大小空闲连接
        bd.setMaxWait(1000);//最大等待时间

        //获得连接
        Connection cn=bd.getConnection();
        //输出连接名
        System.out.println(cn.getClass().getName());


    }

附上BDCP配置信息

#基本配置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb1
username=root
password=123

#初始化池大小,即一开始池中就会有10个连接对象
默认值为0
initialSize=0

#最大连接数,如果设置maxActive=50时,池中最多可以有50个连接,当然这50个连接中包含被使用的和没被使用的(空闲)
#你是一个包工头,你一共有50个工人,但这50个工人有的当前正在工作,有的正在空闲
#默认值为8,如果设置为非正数,表示没有限制!即无限大
maxActive=8

#最大空闲连接
#当设置maxIdle=30时,你是包工头,你允许最多有20个工人空闲,如果现在有30个空闲工人,那么要开除10个
#默认值为8,如果设置为负数,表示没有限制!即无限大
maxIdle=8

#最小空闲连接
#如果设置minIdel=5时,如果你的工人只有3个空闲,那么你需要再去招2个回来,保证有5个空闲工人
#默认值为0
minIdle=0

#最大等待时间
#当设置maxWait=5000时,现在你的工作都出去工作了,又来了一个工作,需要一个工人。
#这时就要等待有工人回来,如果等待5000毫秒还没回来,那就抛出异常
#没有工人的原因:最多工人数为50,已经有50个工人了,不能再招了,但50人都出去工作了。
#默认值为-1,表示无限期等待,不会抛出异常。
maxWait=-1

#连接属性
#就是原来放在url后面的参数,可以使用connectionProperties来指定
#如果已经在url后面指定了,那么就不用在这里指定了。
#useServerPrepStmts=true,MySQL开启预编译功能
#cachePrepStmts=true,MySQL开启缓存PreparedStatement功能,
#prepStmtCacheSize=50,缓存PreparedStatement的上限
#prepStmtCacheSqlLimit=300,当SQL模板长度大于300时,就不再缓存它
connectionProperties=useUnicode=true;characterEncoding=UTF8;useServerPrepStmts=true;cachePrepStmts=true;prepStmtCacheSize=50;prepStmtCacheSqlLimit=300

#连接的默认提交方式
#默认值为true
defaultAutoCommit=true

#连接是否为只读连接
#Connection有一对方法:setReadOnly(boolean)和isReadOnly()
#如果是只读连接,那么你只能用这个连接来做查询
#指定连接为只读是为了优化!这个优化与并发事务相关!
#如果两个并发事务,对同一行记录做增、删、改操作,是不是一定要隔离它们啊?
#如果两个并发事务,对同一行记录只做查询操作,那么是不是就不用隔离它们了?
#如果没有指定这个属性值,那么是否为只读连接,这就由驱动自己来决定了。即Connection的实现类自己来决定!
defaultReadOnly=false

#指定事务的事务隔离级别
#可选值:NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
#如果没有指定,那么由驱动中的Connection实现类自己来决定
defaultTransactionIsolation=REPEATABLE_READ

C3P0

C3P0也是开源免费的连接池。

使用代码

@Test
    public void func() throws PropertyVetoException, SQLException {

        //获得连接池对象
        ComboPooledDataSource cpds=new ComboPooledDataSource();

        //设置4大参数
        cpds.setDriverClass("com.mysql.jdbc.Driver");
        cpds.setJdbcUrl("jdbc:mysql://localhost:3306/sql_test");
        cpds.setUser("root");
        cpds.setPassword("123456");

        //设置池参数
        cpds.setAcquireIncrement(5);//增量
        cpds.setInitialPoolSize(20);//初始池大小
        cpds.setMinPoolSize(3);//最小连接数
        cpds.setMaxPoolSize(40);//最大连接数

        //得到连接对象
        Connection cn=cpds.getConnection();

        //输出连接名
        System.out.println(cn.getClass().getName());
        //归还给池
        cn.close();

    }

配置文件

c3p0使用配置文件有两个要求:

  • 文件名:必须叫c3p0-config.xml
  • 文件位置:必须在src下
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<default-config>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="user">root</property>
		<property name="password">123</property>
		<property name="acquireIncrement">3</property>
		<property name="initialPoolSize">10</property>
		<property name="minPoolSize">2</property>
		<property name="maxPoolSize">10</property>
	</default-config>
	<named-config name="oracle-config">
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="user">root</property>
		<property name="password">123</property>
		<property name="acquireIncrement">3</property>
		<property name="initialPoolSize">10</property>
		<property name="minPoolSize">2</property>
		<property name="maxPoolSize">10</property>
	</named-config>
</c3p0-config>

配置文件中的属性名和java代码中的一致。还可以配置多个连接信息,给每个连接起一个单独的名字。

ComboPooledDataSource ds = new ComboPooledDataSource("orcale-config");

通过连接池更新JDBCUtils工具类

首先是src目录下的配置文件

c3p0-config.xml

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

<c3p0-config>
    <!-- 这是默认配置信息 -->
    <default-config>
        <!-- 连接四大参数配置 -->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/sql_test</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <!-- 池参数配置 -->
        <property name="acquireIncrement">3</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">2</property>
        <property name="maxPoolSize">10</property>
    </default-config>

</c3p0-config>

JDBCUtils.java

/**
 * 使用c3p0连接池
 */
public class JDBCUtils {

    //创建一个连接池对象,这里在配置文件中设置参数 c3p0-config.xml
    private static ComboPooledDataSource cpds=new ComboPooledDataSource();



    /**
     * 返回连接对象
     * @return
     * @throws SQLException
     */
    public static Connection getConnction() throws SQLException {
        return  cpds.getConnection();
    }

    /**
     * 返回连接池对象
     * @return
     */
    public static ComboPooledDataSource getDataSource(){
        return cpds;
    }
}

Tomcat配置连接池

Tomcat配置JNDI资源

JNDI(Java Naming and Directory Interface),Java命名和目录接口。JNDI的作用就是:在服务器上配置资源,然后通过统一的方式来获取配置的资源。

通过在tomcat上配置连接池,在项目中就可以通过统一的方式来获取连接池对象了。

下图是tomcat文档上的:

配置JNDI资源需要到<Context>元素中配置<Resource>子元素:

  1. name:指定资源的名称,这个名称可以随便给,在获取资源时需要这个名称;
  2. factory:用来创建资源的工厂,这个值基本上是固定的,不用修改;
  3. type:资源的类型,我们要给出的类型当然是我们连接池的类型了;
  4. bar:表示资源的属性,如果资源存在名为bar的属性,那么就配置bar的值。对于DBCP连接池而言,你需要配置的不是bar,因为它没有bar这个属性,而是应该去配置url、username等属性。

配置文件这里选择:tomact安装目录下的D:\Program Files\apache-tomcat-8.5.23\conf下的context.xml文件

<?xml version="1.0" encoding="ISO-8859-1"?>
<Context>
    <Resource name="mydbcp"
              type="org.apache.tomcat.dbcp.dbcp.BasicDataSource"
              factory="org.apache.naming.factory.BeanFactory"
              username="root"
              password="123456"
              driverClassName="com.mysql.jdbc.Driver"
              url="jdbc:mysql://localhost:3306/sql_test"
              maxIdle="3"
              maxWait="5000"
              maxActive="5"
              initialSize="3"/>
    <Resource name="myc3p0"
              type="com.mchange.v2.c3p0.ComboPooledDataSource"
              factory="org.apache.naming.factory.BeanFactory"
              user="root"
              password="123"
              classDriver="com.mysql.jdbc.Driver"
              jdbcUrl="jdbc:mysql://127.0.0.1/mydb1"
              maxPoolSize="20"
              minPoolSize ="5"
              initialPoolSize="10"
              acquireIncrement="2"/>
</Context>

获取资源

下图是Tomcat文档提供的,与上面Tomcat文档提供的配置资源是对应的。

  • Context:javax.naming.Context;
  • InitialContext:javax.naming.InitialContext;
  • lookup(String):获取资源的方法,其中”java:comp/env”是资源的入口(这是固定的名称),获取过来的还是一个Context,这说明需要在获取到的Context上进一步进行获取。”bean/MyBeanFactory”对应<Resource>中配置的name值,这回获取的就是资源对象了。

DBCP代码

//获取上下文对象
Context initCtx = new InitialContext();
//通过查询得到数据库池对象
BasicDataSource ds= (BasicDataSource) initCtx.lookup("java:/comp/env/mydbcp");
//获得连接对象
Connection cn=ds.getConnection();
//输出连接名
System.out.println(cn.getClass().getName());
cn.close();

C3P0代码

Context ctx=new InitialContext();
ComboPooledDataSource cpds= (ComboPooledDataSource) ctx.lookup("java:comp/env/myc3p0");
Connection cn=cpds.getConnection();
System.out.println(cn.getClass().getName());
cn.close();

猜你喜欢

转载自blog.csdn.net/SICAUliuy/article/details/88821304