开源数据库连接池
来源:互联网 发布:淘宝鞋店的装饰风格 编辑:程序博客网 时间:2024/04/29 00:58
现在很多WEB服务器(Weblogic、WebSphere、Tomcat)都提供了DataSoruce的实现,即连接池的实现。通常我们把DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现。
也有一些开源组织提供了数据源的独立实现:
- DBCP数据库连接池。
- C3P0数据库连接池。
- Tomcat内置的连接池(其实使用的是Apache DBCP)
实际应用时不需要编写连接数据库代码,直接从数据源获得数据库的连接。程序员编程时也应尽量使用这些数据源的实现,以提升程序的数据库访问性能。
DBCP数据源
DBCP是Apache软件基金组织下的开源连接池实现,要使用DBCP数据源,需要应用程序在系统中增加如下两个jar文件:
- commons-dbcp-1.4.jar:连接池的实现。
- commons-pool-1.6.jar:连接池实现的依赖库。
注意:commons-pool已经到2.0时代了。但是如果使用pool2的包的话,会说找不到类,因为包结构已经变了,不知道怎么配过去,还望赐教啊!!!
Tomcat的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
在应用程序中加入dbcp连接池
导入相关jar包:
- commons-dbcp-1.4.jar
- commons-pool-1.6.jar
在类目录下加入dbcp的配置文件:dbcpconfig.properties。dbcpconfig.properties的配置信息如下:
#连接设置driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/day16username=rootpassword=yezi#<!-- 初始化连接 -->initialSize=10#最大连接数量maxActive=50#<!-- 最大空闲连接 -->maxIdle=20#<!-- 最小空闲连接 -->minIdle=5#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->maxWait=60000#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] #注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。connectionProperties=useUnicode=true;characterEncoding=utf8#指定由连接池所创建的连接的自动提交(auto-commit)状态。defaultAutoCommit=true#driver default 指定由连接池所创建的连接的只读(read-only)状态。#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)defaultReadOnly=#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLEdefaultTransactionIsolation=READ_COMMITTED
如下图所示:
在获取数据库连接的工具类(如jdbcUtils)的静态代码块中创建池。
public class JdbcUtils_DBCP { private static DataSource ds = null; // 静态代码块只执行一次,因为静态代码块在类加载时执行,类永远只加载一次 static { // 初始化连接池 try { InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"); Properties prop = new Properties(); prop.load(in); BasicDataSourceFactory factory = new BasicDataSourceFactory(); ds = factory.createDataSource(prop); } catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException { return ds.getConnection(); // 不会将真正的MySQL驱动返回的Connection返回给你 } public static void release(Connection conn, Statement st, ResultSet rs) { if (rs!=null) { try { rs.close(); // 假设throw异常 } catch (Exception e) { e.printStackTrace(); // 只需在后台记录异常 } rs = null; // 假设rs对象没有释放,将其置为null,该对象就变成垃圾,由Java垃圾回收器回收 } if (st!=null) { try { st.close(); // 假设throw异常 } catch (Exception e) { e.printStackTrace(); // 只需在后台记录异常 } st = null; } if (conn!=null) { try { conn.close(); } catch (Exception e) { e.printStackTrace(); // 只需在后台记录异常 } } }}
测试DBCP数据源。
public class Demo { public static void main(String[] args) throws SQLException, InterruptedException { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try { conn = JdbcUtils_DBCP.getConnection(); System.out.println(conn.getClass().getName()); } finally { JdbcUtils_DBCP.release(conn, st, rs); } }}
运行以上程序,在Eclipse的控制台打印:
org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper
C3P0数据源(Spring内置)
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。
c3p0与dbcp的区别:
- dbcp没有自动回收空闲连接的功能。
- c3p0有自动回收空闲连接的功能。
在应用程序中加入C3P0连接池
导入相关jar包。
- c3p0-0.9.5.2.jar。
- mysql-connector-java-5.1.38-bin.jar
注意:如果操作的是Oracle数据库,那么还需要导入c3p0-oracle-thin-extras-0.9.5.2.jar。
在类目录下加入C3P0的配置文件:c3p0-config.xml。关于该配置文件怎么写,可以参考C3P0数据源的文档。在下载并解压的c3p0-0.9.5.2
文件夹中打开c3p0-0.9.5.2\doc
下的index.html页面,找到如下的位置:
就能知道c3p0-config.xml文件怎么编写了,并且该配置文件的名称一定得是c3p0-config
。
我的c3p0-config.xml文件中的配置信息是这样写的:
<?xml version="1.0" encoding="UTF-8"?><c3p0-config> <!-- C3P0的缺省(默认)配置, 如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源 --> <default-config> <!-- C3P0的属性:driverClass --> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property> <property name="user">root</property> <property name="password">yezi</property> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <!-- 最大空闲时间 --> <property name="maxPoolSize">20</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </default-config> <!-- C3P0的命名配置, 如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("mysql");”这样写就表示使用的是name是mysql的配置信息来创建数据源 --> <named-config name="mysql"> <property name="acquireIncrement">50</property> <property name="initialPoolSize">100</property> <property name="minPoolSize">50</property> <property name="maxPoolSize">1000</property> <!-- intergalactoApp adopts a different approach to configuring statement caching --> <property name="maxStatements">0</property> <property name="maxStatementsPerConnection">5</property> <!-- he's important, but there's only one of him --> </named-config> <named-config name="oracle"> <property name="acquireIncrement">50</property> <property name="initialPoolSize">100</property> <property name="minPoolSize">50</property> <property name="maxPoolSize">1000</property> <!-- intergalactoApp adopts a different approach to configuring statement caching --> <property name="maxStatements">0</property> <property name="maxStatementsPerConnection">5</property> <!-- he's important, but there's only one of him --> </named-config></c3p0-config>
如下图所示:
在获取数据库连接的工具类(如jdbcUtils)的静态代码块中创建池。
public class JdbcUtils_C3P0 { private static ComboPooledDataSource ds = null; // 静态代码块只执行一次,因为静态代码块在类加载时执行,类永远只加载一次 static { // 初始化连接池 try { // 通过读取C3P0的xml配置文件创建数据源,C3P0的xml配置文件c3p0-config.xml必须放在src目录下 ds = new ComboPooledDataSource(); // 使用配置文件的缺省配置,配置文件名称必须是c3p0-config.xml // 通过代码创建C3P0数据库连接池 /* ds.setDriverClass("com.mysql.jdbc.Driver"); ds.setJdbcUrl("jdbc:mysql://localhost:3306/day16"); ds.setUser("root"); ds.setPassword("yezi"); ds.setMaxPoolSize(30); ds.setMinPoolSize(5); ds.setInitialPoolSize(10); */ } catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException { return ds.getConnection(); // 不会将真正的MySQL驱动返回的Connection返回给你 } public static void release(Connection conn, Statement st, ResultSet rs) { if (rs!=null) { try { rs.close(); // 假设throw异常 } catch (Exception e) { e.printStackTrace(); // 只需在后台记录异常 } rs = null; // 假设rs对象没有释放,将其置为null,该对象就变成垃圾,由Java垃圾回收器回收 } if (st!=null) { try { st.close(); // 假设throw异常 } catch (Exception e) { e.printStackTrace(); // 只需在后台记录异常 } st = null; } if (conn!=null) { try { conn.close(); } catch (Exception e) { e.printStackTrace(); // 只需在后台记录异常 } } }}
测试C3P0数据源。
public class Demo { public static void main(String[] args) throws SQLException, InterruptedException { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try { conn = JdbcUtils_C3P0.getConnection(); System.out.println(conn.getClass().getName()); } finally { JdbcUtils_DBCP.release(conn, st, rs); } }}
运行以上程序,在Eclipse的控制台打印:
配置Tomcat数据源
在实际开发中,我们有时候还会使用服务器提供给我们的数据库连接池,比如我们希望Tomcat服务器在启动的时候可以帮我们创建一个数据库连接池,那么我们在应用程序中就不需要手动去创建数据库连接池,直接使用Tomcat服务器创建好的数据库连接池即可。要想让Tomcat服务器在启动的时候帮我们创建一个数据库连接池,那么需要简单配置一下Tomcat服务器。
JNDI技术简介
JNDI(Java Naming and Directory Interface),Java命名和目录接口,它对应于J2SE中的javax.naming包。
这套API的主要作用在于:它可以把Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需通过名称检索即可。其核心API为Context,它代表JNDI容器,其lookup方法为检索容器中对应名称的对象。
Tomcat服务器创建的数据源是以JNDI资源的形式发布的,所以说在Tomat服务器中配置一个数据源实际上就是在配置一个JNDI资源,通过查看Tomcat文档,我们知道使用如下的方式配置tomcat服务器的数据源:
<Context> <Resource name="jdbc/EmployeeDB" auth="Container" type="javax.sql.DataSource" username="root" password="yezi" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/day16" initialSize="10" maxActive="30" maxIdle="4"/></Context>
服务器创建好数据源之后,我们的应用程序又该怎么样得到这个数据源呢,Tomcat服务器创建好数据源之后是以JNDI的形式绑定到一个JNDI容器中的,我们可以把JNDI想象成一个大大的容器,我们可以往这个容器中存放一些对象,一些资源,JNDI容器中存放的对象和资源都会有一个独一无二的名称,应用程序想从JNDI容器中获取资源时,只需要告诉JNDI容器要获取的资源的名称,JNDI根据名称去找到对应的资源后返回给应用程序。
总结:我们平时做javaEE开发时,服务器会为我们的应用程序创建很多资源,比如request对象,response对象,服务器创建的这些资源有两种方式提供给我们的应用程序使用:
- 第一种是通过方法参数的形式传递进来,比如我们在Servlet中写的doPost和doGet方法中使用到的request对象和response对象就是服务器以参数的形式传递给我们的。
- 第二种就是JNDI的方式,服务器把创建好的资源绑定到JNDI容器中去,应用程序想要使用资源时,就直接从JNDI容器中获取相应的资源即可。
又可以这样总结:在服务器下做编程,我们要获取一个资源,现在多了一种新的方式。以前,一个浏览器去访问服务器时,服务器调用你的servlet,会传递一些对象给你,对象是怎么传递给你的呢?都是调用你servlet的方法时,把对象传递给你。现在我们学了这种模型之后,将来在服务器下做开发,服务器还有一种方式传对象给你,并不是在调用你servlet的方法时,把对象作为参数传递给你,而是会把对象放在一个JNDI容器里面,你需要的时候就从容器里面取。
对于上面的name=”jdbc/EmployeeDB”数据源资源,在应用程序中可以用如下的代码去获取:
Context initCtx = new InitialContext(); // 初始化JNDIContext envCtx = (Context) initCtx.lookup("java:comp/env");dataSource = (DataSource)envCtx.lookup("jdbc/EmployeeDB");
用图来表示即为:
配置Tomcat数据源
为了配置Tomcat数据源,我们可参考Tomcat服务器文档(http://localhost:8080/docs/config/context.html),找到如下的位置:
注意上面标红的句子,我们重点关注这句话。
In an individual file at /META-INF/context.xml inside the application files.
翻译过来大致意思就是: 一个单独的文件,在应用程序文件/META-INF/context.xml内。
这句话告诉我们应该在Web项目的WebRoot目录下的META-INF目录创建一个context.xml文件。
如下图所示:
更加详细的内容我们可以参考我以前的笔记JavaWeb开发入门(二)——虚拟目录的映射方式三。
context.xml文件创建出来了,怎么编写里面的内容呢?所以我们又要参考Tomcat服务器的文档(http://localhost:8080/docs/jndi-resources-howto.html)了,找到如下的位置:
对应着以上代码修修改改就可以了。
现在在context.xml文件配置tomcat服务器的数据源。
<?xml version="1.0" encoding="UTF-8"?><Context> <Resource name="jdbc/EmployeeDB" auth="Container" type="javax.sql.DataSource" username="root" password="yezi" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/day16" initialSize="10" maxActive="30" maxIdle="4"/></Context>
以上为某一个web应用配置了一个资源,资源的类型是javax.sql.DataSource,即配置了一个连接池,tomcat在启动的时候就会为你的web应用创建一个连接池,并且tomcat会把这个连接池以JNDI的资源的形式绑定到jdbc/EmployeeDB这么一个名称上面去,即你的应用程序等一会要用连接池,只需根据这个名称检索就行了,就可拿到连接池。 auth="Container"
:该参数指定由容器来创建连接池。
接着将数据库的驱动jar文件需放置在tomcat的lib下。如下图所示:
特别提醒:此种配置下,数据库的驱动jar文件需放置在tomcat的lib下。再说一遍,千万注意,由于是服务器来创建连接池,所以说数据库驱动jar包一定要加到tomcat服务器的lib目录里面去。否则,会报异常:
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
在获取数据库连接的工具类(如jdbcUtils)的静态代码块中获取JNDI容器中的数据源
在cn.itcast.utils包下创建获取数据库连接的工具类——JdbcUtils.java,JdbcUtils类的代码如下所示:
public class JdbcUtils { private static DataSource ds = null; static { try { Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); ds = (DataSource) envCtx.lookup("jdbc/EmployeeDB"); } catch (Exception e) { throw new RuntimeException(e); } } public static Connection getConnection() throws SQLException { return ds.getConnection(); }}
写一个小程序来测试JNDI数据源。
在cn.itcast.dao包下创建一个类——Dao.java,其代码如下所示:
public class Dao { public void add() { Connection conn = null; try { conn = JdbcUtils.getConnection(); } catch (SQLException e) { e.printStackTrace(); } System.out.println(conn); }}
在cn.itcast.web.servlet包下创建一个Servlet——Servlet1.java,其代码如下所示:
public class Servlet1 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Dao dao = new Dao(); dao.add(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
在浏览器中输入访问服务器的地址http://localhost:8080/day16_datasource/Servlet1
,然后可以在Eclipse的控制台下看到如下结果:
- 开源数据库连接池
- 开源数据库连接池
- 开源数据库连接池
- 开源数据库连接池汇总
- 开源数据库连接池proxool
- 开源数据库连接池的比较
- JAVA开源数据库连接池C3P0简介
- 开源数据库连接池Bonecp应用
- 阿里巴巴开源数据库连接池Druid
- 开源数据库连接池(dbcp实例)
- 开源数据库连接池的使用
- SQL RELAY开源数据库连接池
- JAVA开源数据库连接池比较
- 常用的开源数据库连接池比较
- 常见开源数据库连接池的使用
- C3P0(开源的数据库连接池)
- 开源的数据库连接池 SQL Relay 介绍
- 开源的数据库连接池 SQL Relay 介绍
- Ubuntu,Windows下jdk环境配置
- ccf201512-2消除类游戏
- pads布局布线技巧(【PCB文件中显示引脚号】 【敷铜】 【显示网络名】 【高亮网络】 【修改PCB中文本的尺寸】 【同时修改多个文本(对象)的尺寸(属性) 让集中在一起的元件散开)
- UVA - 563 Crimewave【最大流】
- Application类
- 开源数据库连接池
- ubuntu15.1安装openssh-server失败问题
- Toast优化*
- 嵌入式Ubuntu系统开机运行程序(一)
- poj1252
- Active之入门HelloWorld
- openwrt编译自己的package时遇到缺失libpthread.so.0依赖的问题
- http1 jdk版,本来不想copy别人的,但是看到正好可以对比下,就弄过来了
- 鸡兔同笼:笼子里一共有鸡和兔子35只,一共有94条退, 笼子里一共有鸡和兔子共多少只