目标
使用C3P0创建数据源DataSource。
使用DBCP创建据源DataSource。
能够使用JDBC简化工具包DBUtils完成单表的增删改查操作。
1.为什么使用连接池重写工具类
1.因为每次创建和销毁连接都会消耗较多的系统资源
2.每次创建和销毁连接都要消耗大概0.05~1s的时间。
3.可以防止大量用户并发访问数据库服务器。
Connection对象在JDBC使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了.每次创建和销毁对象都是耗时操作.需要使用连接池对其进行优化.程序初始化的时候,初始化多个连接,将多个连接放入到池(集合)中.每次获取的时候,都可以直接从连接池中进行获取.使用结束以后,将连接归还到池中.
2.连接池原理
目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能。
3.编写连接池
3.1步骤
创建一个类,定义LinkedList集合作为连接池,在静态代码块中,向集合里面添加5个连接对象
添加addBack()方法,用作归还连接
代码:
public class MyDataSource {
//连接池
static LinkedList pool = new LinkedList<>();
//初始化连接
static{
try {
for(int i = 0; i < 5; i++){
pool.add(JdbcUtils.getConnection());
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//定义一个方法,从连接池中获取connection,从头部获取
public Connection getConnectionFromPool(){
if (pool.size() > 0) {
//池子中有connection
return pool.removeFirst();
}else {
//如果池子中没有connection,则先加入等待队列,等待队列满了的话就新建connection(新建的 //connection是不需要放回池子的,用完后直接销毁)
return JDBCUtil.getConnection();
}
}
//定义一个方法,将connection放回池子中(如果是新创建的connection则直接销毁)
public void addBack(Connection connection){
//pool.addLast(connection);//免不了会将新建的connection添加进池子;
try {
//写一个自己的connection,然后重写close()方法,通过close()方法来添加进池子。
connection.close();//免不了会将池子中的connection销毁
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//返回pool里面连接的个数
public int getCount(){
return pool.size();
}
}
3.2 编写连接池遇到的问题
如果新建了connection,用完之后怎么判别是原池子中的connection(需要放回去),还是新建的connection(需要销毁)。
3.3解决办法(自定义一个 Connection,重写close方法)
继承 条件:可以控制父类的构造
装饰者模式
目的:改写已存在的类的某个方法或某些方法,装饰设计模式(包装模式)
条件:1.包装类和被包装类实现同一个接口
2.包装类里面要拿到被包装类的引用
步骤:
编写一个类实现一个接口,为被包装类
编写一个类,实现与被包装类相同的接口。(具备相同的行为)
定义一个被包装类类型的变量。
定义构造方法,把被包装类类的对象注入,给被包装类变量赋值。
对于不需要改写的方法,调用被包装类类原有的方法。
对于需要重写的方法,写自己的代码。
动态代理(类似装饰者模式,此处不学)
3.4datasource接口概述
Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商(用户)需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!
常见的连接池:DBCP、C3P0。
4.常用连接池
4.1 dbcp
4.1.1 dbcp概念
"DBCP" redirects here. For the database connection pool implementation, see Apache Commons.
1,2-Dibromo-3-chloropropane, (dibromochloropropane) better known as DBCP, is the active ingredient in the nematicide Nemagon, also known as Fumazone.
It is a soil fumigant formerly used in American agriculture. In mammals it causes male sterility at high levels of exposure. After discovery of its deleterious health effects on humans, the compound was banned from use in 1979 by the United States Environmental Protection Agency (EPA).[3] The continuing presence of the chemical as a contaminant in ground water remains a problem for many communities for years after end of use.
DBCP:Apache推出的 Database Connection Pool
核心API:
basicDatasource
basicDatasourceFactory
4.1.2使用步骤
添加jar包 commons-dbcp-1.4.jar commons-pool-1.5.6.jar
添加配置文件到src目录
编写数据源工具类
通过配置文件来编写
public class DBCPUtils {
static DataSource ds;
static {
//只需要初始化一次
try {
Properties p = new Properties();
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
// InputStream is = new FileInputStream("src/dbcpconfig.properties");
p.load(is);
ds = BasicDataSourceFactory.createDataSource(p);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 创建连接
public static Connection getConnection() throws SQLException {
// DriverManager.getConnection(url, user, password); Connection
Connection connection = ds.getConnection();
return connection;
}
// 释放资源
public static void release(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();//不要关注方法名,关注连接来源
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
通过硬编码来表写(不需要配置文件.了解一下)
DataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://localhost:3306/day01_1");
basicDataSource.setUsername("root");
basicDataSource.setPassword("123456");
4.2 c3p0
4.2.1 c3p0概念
C3P0开源免费的连接池!目前使用它的开源项目有:Spring、Hibernate等。使用第三方工具需要导入jar包,c3p0使用时还需要添加配置文件c3p0-config.xml
4.2.2使用步骤
添加jar包
编写配置文件c3p0-config.xml,放在src中(注:文件名一定不要写错)
通过配置文件来编写
public class C3P0Utils {
//创建一个连接池对象
static DataSource ds = new ComboPooledDataSource();
//从池中获得一个连接
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
//释放资源
public static void release(ResultSet rs,Statement stmt,Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
rs = null;
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
stmt = null;
}
if(conn!=null){
try {
conn.close();//放心的关。是否关闭取决连接是怎么来的
} catch (SQLException e) {
throw new RuntimeException(e);
}
conn = null;
}
}
}
通过硬编码来编写(不需要配置文件.了解一下)
DataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver"); // loads the jdbc driver
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/day10");
cpds.setUser("root");
cpds.setPassword("123");
4.3 druid连接池
Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
druid连接池的使用
使用硬编码方式
//创建一个DruidDataSource()对象
DruidDataSource dataSource = new DruidDataSource();
//设置用户名
dataSource.setUsername("root");
//设置密码
dataSource.setPassword("123");
//设置驱动类名
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
//设置初始化连接数
dataSource.setInitialSize(10);
//获得连接
Connection connection = dataSource.getConnection();
使用配置文件
//创建Properties对象 Properties properties = new Properties(); //加载配置文件 properties.load(new FileInputStream("src/druidconfig.properties")); //创建使用连接池工厂创建连接池 DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); //获得连接 Connection connection = dataSource.getConnection();
1.案例分析
简化JDBC代码开发,本案例我们将采用apache commons组件一个成员:DBUtils。
DBUtils就是JDBC的简化开发工具包。需要使用技术:连接池(获得连接)、SQL语句都没有少
2.案例相关知识
2.1javaBean组件
JavaBean就是一个类,在开发中常用于封装数据。具有如下特性
1.需要实现接口:java.io.Serializable ,通常偷懒省略了。2.提供私有字段:private 类型 字段名;3.提供getter/setter方法:4.提供无参构造
public class Category {
private String cid;
private String cname;
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
}
3.DBUtils完成CRUD
3.1概述
DBUtils是java编程中的数据库操作实用工具,小巧简单实用。 第一个操作数据库框架(jar),
DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
Dbutils三个核心功能介绍
QueryRunner中提供对sql语句操作的API. update(), query()
ResultSetHandler接口,用于定义select操作后,怎样封装结果集.
DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法
3.2QueryRunner核心类
QueryRunner(DataSource ds) ,提供数据源(连接池),DBUtils底层自动维护连接connection
update(String sql, Object... params) ,执行更新数据 insert update delete 参数就是一个数组,参数个数取决于语句中?的个数
query(String sql, ResultSetHandler
3.3ResultSetHandler结果集处理类
Handler类型 | 说明 |
---|---|
ArrayHandler | 将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值 |
ArrayListHandler | 将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。 |
BeanHandler | 将结果集中第一条记录封装到一个指定的javaBean中。 |
BeanListHandler | 将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中 |
ColumnListHandler | 将结果集中指定的列的字段值,封装到一个List集合中 |
KeyedHandler | 将结果集中每一条记录封装到Map |
MapHandler | 将结果集中第一条记录封装到了Map |
MapListHandler | 将结果集中每一条记录封装到了Map |
ScalarHandler | 它是用于单个数据。例如select count(*) from 表操作。 |
3.4练习
3.4.1开发步骤:
创建项目,并导入jar包
创建连接池
编写测试类
3.4.2增加
//向user表添加一条数据
@Test
public void insert() throws SQLException{
//创建queryRunner对象
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
//String sql = "insert into user values(null,'aaa','111','露西')";
String sql = "insert into user values(?,?,?,?)";
Object[] params ={null,"aaa","111","露西"};
queryRunner.update(sql, params);
}
3.4.3更新
//把用户名是aaa的user密码改成222
@Test
public void update() throws SQLException{
//创建queryRunner对象
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "update user set password = ? where username = ?";
Object[] params={"222","aaa"};
queryRunner.update(sql, params);
}
3.4.4删除
//把用户名是aaa的user给删除
@Test
public void delete() throws SQLException{
//创建queryRunner对象
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "delete from user where username = ?";
Object[] params={"aaa"};
queryRunner.update(sql, params);
}
3.4.5通过id查询
//查询id为1的用户信息
@Test
public void selectById() throws SQLException{
//创建queryRunner对象
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "select *from user where id = ?";
Object[] params = {1};
User user = queryRunner.query(sql, new BeanHandler<>(User.class), params);
System.out.println(user.toString());
}
3.4.6查询所有列
//查询所有的用户信息
@Test
public void selectAll() throws SQLException{
//创建queryRunner对象
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "select *from user";
Object[] params = {};
List list = queryRunner.query(sql, new BeanListHandler<>(User.class), params);
System.out.println(list.toString());
}
3.4.7 总记录数
//统计用户的个数
@Test
public void getCount() throws SQLException{
//创建queryRunner对象
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "select count(*) from user";
Long n = (Long) queryRunner.query(sql, new ScalarHandler());
System.out.println(n.intValue());
}