目标:连接池
一. 自定义连接池
使用DBUtils组件更新和查询数据库
QueryRunner qr = new QueryRunner();
qr.query(con,sql,rsh);
//rsh:ResultSetHandler接口,可以使用自定义实现类,改写handle()方法;也可以使用封装的实现类。
List<Person> list = qr.query(con,sql,new BeanListHandler<Person>(Person.class))
1. 思考:程序中连接如何管理?
- 连接资源很宝贵,MySQL最多大约200个连接,不够用
- 连接:
- 创建连接,操作数据库
- 操作结束,关闭连接
- 频繁打开关闭,影响效率:
- 解决方案:预先创建一组连接,用则取出,用完释放;这些预先创建的连接存放在连接池(集合)中。
- 学习连接池:
- 自定义连接池
- 程序实现思路:
- 指定初始化连接数目,app启动时,就执行创建!
- 指定最大连接数
- 指定当前使用连接个数:不能超出最大连接数
- 代码实现
- MyPool.java连接池类;
- 指定全局参数:初始化数目,最大连接数,当前连接数,连接池集合
- 构造函数:循环创建3个连接–写一个创建连接的方法
- 获取连接:
- 池中有连接,直接拿
- 池中没有连接,判断现有总连接数,若达到最大连接数,抛出异常;没有达到最大连接数,创建新的连接
- 释放连接:连接放回连接池集合中
- 通常,连接使用完,会采用connection.close()方法关闭与数据库的连接。这里,不应该频繁关闭连接,应该把该连接重新放入连接池(保证连接池中的和活跃的连接总数不大于最大连接数即可),留给下一个用户使用。
2. 代理模式:
- 想对接口中某个或部分方法的功能进行扩展,而不像实现接口,可以使用(动态)代理模式 Java中有静态/动态/Cglib(spring)代理模式
- 通过创建某个接口对象的代理对象,实现对接口中某个方法的监测,从而达到,不需要重写接口的所有方法,也可以修改或者扩展接口中某个方法的目的!
在使用代理模式时:
Proxy static Object new ProxyInstance(
ClassLoader loader, //当前使用的类加载器this.getClass().getClassLoader()
Class<?>[] interfaces,//获取接口对象实现的接口类型
InvocationHandler h //事件处理器,当该对象执行接口中的方法时,会触发事件处理器代码,可以将需要改变的方法作为参数(method)传入;
);
获取具体类实现的接口:
obj.getClass().getInterfaces();
获取接口对象实现的接口
new Class[]{Object.class};
二. DBCP和C3P0连接池技术
通常我们把对接口 javax.sql.DataSource的实现,称为数据源,数据源中包含了数据库连接池的实现。由一些开源组织提供了数据源的独立实现:
- DBCP(tomcat)数据库连接池
- Commons-dbcp.jar
- Commons-pool.jar
- C3P0(hibernate)数据库连接池
- c3p0.jar
1. DBCP连接池
核心类:BasicDataSource
@Test
public void testConfig() throws Exception {
Properties prop = new Properties();
InputStream in = DBCP_demo.class.getResourceAsStream("/db.properties");
prop.load(in);
DataSource dataSource = BasicDataSourceFactory.createDataSource(prop);
Connection conn = dataSource.getConnection();
PreparedStatement pstm = conn.prepareStatement("insert into employee values(?,'chenchen','nv',29,'dsadioua','dw@eewe','43243243');");
pstm.setObject(1, 8);
pstm.executeUpdate();
conn.close();
}
使用配置文件获取数据源配置
- 何时使用properties,何时使用xml来配置?
- properties实现HashTable接口!存放的只是键值对
db.properties
url=jdbc:mysql://localhost:3306/day17
driverClassName=com.mysql.jdbc.Driver
username=root
password=root
initalSize=3
maxActive=6
maxIdle=5000
//注意key需要和DBCP的方法名匹配
2. C3P0连接池
最常用的连接技术,Spring和Hibernate框架支持C3P0连接池技术
核心类:CombopooledDataSource ds;
1. 硬编码方法
@Test
public void testC3P0() throws Exception {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setJdbcUrl("jdbc:mysql://localhost:3306/day17");
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setUser("root");
ds.setPassword("root");
ds.setInitialPoolSize(3);
ds.setMaxPoolSize(6);
ds.setMaxIdleTime(1000);
Connection conn = ds.getConnection();
PreparedStatement pstm = conn.prepareStatement("delete from employee where id=?");
pstm.setObject(1, 3);
pstm.executeUpdate();
conn.close();
}
2. XML配置方式
自动加载src目录下的c3p0-config.xml文件,配置连接池
@Test
public void testname() throws Exception {
//自动加载src目录下的c3p0-config.xml配置文件
ComboPooledDataSource ds = new ComboPooledDataSource();
Connection conn = ds.getConnection();
conn.prepareStatement("delete from employee where id=4;").execute();
conn.close();
}
注意:property的name属性必须小写开头,再使用驼峰式命名!
<default-config>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day17</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">10</property>
<property name="maxPoolSize">25</property>
<property name="maxIdleTime">3000</property>
</default-config>
也可以使用特定的数据库配置
//获取连接池配置文件信息
ComboPooledDataSource ds = new ComboPooledDataSource("oracle-config");
<named-config name="oracle-config">
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day17</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">10</property>
<property name="maxPoolSize">25</property>
<property name="maxIdleTime">3000</property>
</named-config>
使用d3p0连接池技术-步骤:
- 导入jar包
- 改写xml配置文件
- 创建数据源,获得连接,传递sql语句执行,关闭连接
三. 连接的管理
交给连接池!改写项目中DBUtils类