连接池
连接池介绍
- 获取服务器连接和断开连接是非常消耗系统资源的,重复创建和断开连接会造成资源浪费
- 使用数据库连接池可以解决性能问题
- 使用连接池技术来共享Connection
- java为数据库连接池提供了公共的接口:javax.sql.DataSource
自定义连接池
- 数据源
- 获取数据的资源,我们以后需要获取数据库数据,就从连接池中获取连接然后连到数据库里,称之为数据源
- 创建连接池步骤
- 创建连接池实现(实现javax.sql.DataSource接口),使用getConnection()方法
- 提供一个集合,用于存放连接,因为移除和添加操作过多,因此选择LinkedList
- 通过自定义的JDBCUtils获取Connection
- 在静态代码块中创建3个连接
- 程序需要连接,调用getConnection()方法,方法从LinkedList中获取连接
- 用户使用完连接后把连接添加回LinkedList中
public class MyDataSource implements DataSource{
private static LinkedList<Connection> pool = new LinkedList<>();
private MyDataSource() {
super();
}
static {
Connection conn = null;
for (int i = 0; i < 15; i++) {
conn = JDBCUtils.getConnection();
pool.add(conn);
}
}
@Override
public static Connection getConnection() throws SQLException {
if (pool.size() != 0) {
return pool.removeFirst();
}
Thread.sleep(100);
return getConnection();
}
//回收连接
public static releaseConnection(Connection conn) {
if(conn != null) {
pool.add(conn);
}
}
}
- 自定义连接池需要调用连接池提供的release(connection conn)方法进行回收连接
- 如果用户调用Connection.close()会真的关闭掉连接
- 我们需要当用户调用Connection的close方法后,连接重新回到链接池中
- 实现Connection.close()后连接回到连接池中
方法增强
1. 继承:子类继承父类,重写父类的方法从而使方法增强
* 前提是必须要有父类,且存在继承关系
2. 装饰设计模式:此设计模式专门用于增强方法
* 使用前提:必须有接口
* 缺点:需要将接口所有方法实现
3. 动态代理:在运行时动态的创建代理类,完成增强的操作,与装饰者相似
* 使用前提:需要有接口
* 难点:需要有反射技术
4. 字节码增强:运行时创建目标类子类,从而进行增强
* 常见第三方框架:cglib,javassist等
装饰设计模式
- 专门为解决某一类问题,而编写的固定格式的代码
- 装饰者固定结构:接口A,已知实现类C,需要装饰者创建代理类B
- 创建B,并实现A接口
- 提供B类的构造方法,参数类型为A,用于接收A接口的实现类C
- 给类B添加类型为A的成员变量,用于存放A接口的其他实现类
- 增强需要的方法
- 实现不需要增强的方法,方法体重调用成员变量存放的其他实现类对应的方法
- A接口的实现类C作为参数传递,需要增强C的某个方法,创建A接口实现类B包裹C,修改该方法,然后把B替代C作为参数传递
A a = c;
B b = new B(c);
class B implement A {
private A a;
public B(A a) {
this.a = a;
}
//需要增强的方法
public void close() {
...
}
//需要增强的方法
public void commit() {
...
}
}
//1.实现同一个接口Connection
public class MyConnection implements Connection {
//3.定义一个变量
private Connection conn;
private LinkedList<Connection> pool;
// 2.编写一个构造方法(参数使用了面相对象的多态特性)
public MyConnection(Connection conn,LinkedList<Connection> pool) {
this.conn=conn;
this.pool=pool;
}
//4.书写需要增强的方法
@Override
public void close() throws SQLException {
pool.add(conn);
}
/**
* 此方法必须覆盖!否则会出现空指针异常!!!
*/
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return conn.prepareStatement(sql);
}
}
C3P0连接池(使用率最高80%)
-
C3P0是开源免费的连接池,目前使用它的开源项目有:Spring,Hibernate等.
-
使用第三方工具需要导入jar包,C3P0使用时还需要添加配置文件c3p0-config.xml
-
c3p0工具类
//创建空参的ComboPooledDataSource对象时,默认会自动读取c3p0-config.xml文件中的<default-config>配置
public class C3P0Utils {
private static ComboPooledDataSource dataSource = new ComboPooledDataSource("coinfig_name");
public static DataSource getDataSource() {
return dataSource;
}
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
- c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///web08</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<named-config name="myconfig">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///web08</property>
<property name="user">root</property>
<property name="password">root</property>
</named-config>
</c3p0-config>
DBCP
- DBCP也是开源免费的连接池,在企业开发中也比较常见
- tomcat服务器自带DBCP连接池
- DBCP可以自己手动设置参数,也可以通过Properties对象和BasicDataSourceFactory初始化
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.Driver");
basicDataSource.setUrl("jdbc:mydql://localhost:3306/mydatabase");
basicDataSource.setUsername("root");
basicDataSource.setPassword("root");
public class DBCPUtils {
private static DataSource dataSource;
static{
try {
//1.加载找properties文件输入流
InputStream is = DBCPUtils.class.getClassLoader().getResourceAsStream("db.properties");
//2.加载输入流
Properties props = new Properties();
props.load(is);
//3.创建数据源
dataSource = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static DataSource getDataSource(){
return dataSource;
}
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
- 配置文件:db.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/web08?useUnicode=true&characterEncoding=utf8
username=root
password=root
initialSize=10
maxActive=50
maxIdle=5
maxWait=6000
DBUtils
- DBUtils是java编程中操作数据库的实用工具,小巧简单
- DBUtils封装了对JDBC操作,可以减少代码
- DBUitls,JDBCUtils,连接池区别
- JDBCUtils是方便获取连接
- 数据库连接池是提高代码的性能
- DBUtils是精简操作数据库代码量
- DBUtils类在基础加强里面会单独讲
try {
// 1.创建核心类QueryRunner
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());//参数传入连接池
// 2.编写SQL语句
String sql = "insert into tbl_user values(null,?,?)";
// 3.为站位符设置值
Object[] params = { "xx", "oo" };
// 4.执行添加操作
int rows = qr.update(sql, params);
if (rows > 0) {
System.out.println("添加成功!");
} else {
System.out.println("添加失败!");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
网友评论