提纲:
1.数据库连接池介绍以及如何自定义数据库连接池
2.介绍两种连接库连接池DBCP,c3p0(文后附jar包)
3.tomcat管理连接池.
##DataSource(数据源/数据库连接池 )简单介绍
连接池:创建多个Connection对象,放入到连接池(其实就是一个容器)中
当使用时,从连接池中取出一个连接对象,使用完成后,再将这个对象
放回到池中.
编写连接池需要实现javax.sql.DataSource接口
自定义连接池步骤
1.创建类实现 DataSource接口
2.重写getConnection方法
3.创建一个LinkedList集合
4.在构造方法中向集合中添加多个Connection对象
5.在getConnection方法中,从集合中获取Connection对象返回(removeFirst())
6.定义一个closeCon方法,用于回收使用后的Connection对象
下面来演示一下自定义连接池:
package cn.lawfree.datasource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;
import javax.sql.DataSource;
import cn.itcast.JDBC.util.JdbcUtil;
public class MyDataSource implements DataSource {
// 定义一个容器用来装入Connection.
private LinkedList conns = new LinkedList();
// 定义构造方法
public MyDataSource() {
for (int i = 0; i < 10; i++) {
conns.add(JdbcUtil.getConnection());
}
}
@Override
public Connection getConnection() throws SQLException {
// 若连接池中没有连接对象,重新创建三个
if (conns.size() == 0) {
for (int i = 0; i < 3; i++) {
return conns.removeFirst();
}
}
return conns.removeFirst();
}
// 用来回收连接对象
public void closeConnection(Connection conn) {
conns.add(conn);
}
@Override
public Connection getConnection(String arg0, String arg1)
throws SQLException {
return null;
...
**问题:*为了不依赖于自定义的API,而是可以直接使用java.sql. ,java.sql.*中的API
怎样解决 con.close()时不是销毁con对象,而是将对象重新放到连接池中
**分析:**原本close方法是销毁Connection对象,现在要将这个方法的功能进行改变(增强)
解决方案
1.重写.
2.装饰模式
装饰特点
1.在装饰类中定义被装饰对象
2.通过构造方法接收被装饰对象
3.装饰类与被装饰类一般会实现同一接口,或继承同一类动态代理
3. 动态代理
要求可以动态产生一个类的代理对象
我们可以在其中对某些要执行的内容进行控制
例如,我们现在要做的是是当Connection对象执行close方法时,将Connection对象放回到连接池当中
当close方法执行时,我们可以屏蔽掉原来的执行内容,而是执行我们的内容,这样就可以达到目的
###DBCP连接池
怎样使用DBCP连接池
1.所有应用jar文件添加到工程中
2. 关于dbcp连接池使用有两种方式
(1)手动
(2)配置文件
记住BasicDataSource类
下面还是演示一下DBCP连接池:
package cn.lawfree.datasource.dbcp;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test;
public class DemodDbcp {
// 看看连接池吧
@Test
public void fun() throws SQLException {
BasicDataSource bds = new BasicDataSource();
// 通过BasicDataSource提供的setxxx方法将driver,url,username,password赋值
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setUrl("jdbc:mysql:///mydb");
bds.setUsername("root");
bds.setPassword("124816qwert");
for (int i = 0; i < 100; i++) {
Connection con = bds.getConnection();
System.out.println(con + " " + con.hashCode());//通过结果我们发现是只有一个对象(得到的似乎总是他~)
con.close();
}
}
// 手动配置
@Test
public void fun1() throws SQLException {
// BasicDataSource bds = new BasicDataSource();// 创建数据源
BasicDataSource bds = new BasicDataSource();
// 通过BasicDataSource提供的setxxx方法将driver,url,username,password赋值
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setUrl("jdbc:mysql:///mydb");
bds.setUsername("root");
bds.setPassword("123456");
// 获取连接对象
Connection con = bds.getConnection();
// 获取操作对象
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from account");
while (rs.next()) {
System.out.println(rs.getString("name") + " "
+ rs.getDouble("money"));
}
con.close();
}
// 通过配置文件
@Test
public void fun3() throws Exception {
Properties props = new Properties();// Properties就是hashmap的子类
props.put("driverClassName", "com.mysql.jdbc.Driver");
props.put("url", "jdbc:mysql:///mydb");
props.put("username", "root");
props.put("password", "123456");
// 1.创建数据源工厂
BasicDataSourceFactory factory = new BasicDataSourceFactory();
// 2.得到数据源对象
DataSource ds = factory.createDataSource(props);
// 获取连接对象
Connection con = ds.getConnection();
Statement st = con.createStatement();
String sql = "select * from account";
ResultSet rs = st.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getString("name") + " "
+ rs.getDouble("money"));
}
con.close();
}
}
###C3P0连接池
手动配置
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql:///day12");
cpds.setUser("root");
cpds.setPassword("124816qwert");
自动配置
ComboPooledDataSource cpds=new ComboPooledDataSource();
在src下创建c3p0-config.xml文件
c3p0.properties文件
当创建cpds时,会自动在classpath下查找配置文件
老样子,配上示例代码…
package cn.lawfree.datasource.c3p0;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DemoC3p0 {
// 手动
@Test
public void fun1() throws PropertyVetoException, SQLException {
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql:///mydb");
cpds.setUser("root");
cpds.setPassword("123456");
Connection con = cpds.getConnection();
// 获取操作对象
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from account");
while (rs.next()) {
System.out.println(rs.getString("name") + " "
+ rs.getDouble("money"));
}
con.close();
}
// 配置文件
@Test
public void fun2() throws SQLException {
ComboPooledDataSource cpds = new ComboPooledDataSource();
Connection con = cpds.getConnection();
// 获取操作对象
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from account");
while (rs.next()) {
System.out.println(rs.getString("name") + " "
+ rs.getDouble("money"));
}
}
}
###tomacat服务器管理连接池
将连接池交给web服务器管理----web应用
既然是web应用,怎样获取连接对象?
JNDI
怎样在tomcat服务器中配置数据源?
在tomcat/conf/context.xml文件,在这个文件中可以配置
但是配置配置后的数据源,服务器下的所有web应用都可以使用
怎样配置成只针对当前web应用的数据源
在META-INF下创建一个context.xml文件:
####tomcat管理连接池步骤
1.在META-INF下创建一个context.xml文件
2.将mysql驱动添加到tomcat/lib
3.创建一个servlet类
4.在servlet中获取数据源对象DataSource
Context initCtx;
DataSource dataSource = null;
try {
initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
dataSource = (DataSource) envCtx.lookup("jdbc/datasource");