主要遇到的问题:
->DAO的实现方式不止JDBC一种,所以要写一个DAO接口,然后用JDBC来实现,实现其中的方法
->如果要通用的话,必须要泛型,可是 queryRunner 中的部分方法要获取 存储对象的class文件,要考虑如何获取 T.class
UML图
1.配置 c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="helloc3p0">
<!-- 指定连接数据源的基本属性 -->
<property name="user">root</property>
<property name="password">1995</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///db_javaee</property>
<!-- 若服务器中连接数不足时,一次向数据库服务器申请多少个连接 -->
<property name="acquireIncrement">50</property>
<!-- 初始化数据库连接池时连接的数量 -->
<property name="initialPoolSize">5</property>
<!-- 数据库连接池中的最小的数据库连接数 -->
<property name="minPoolSize">50</property>
<!-- 数据库连接池中的最大的数据库连接数 -->
<property name="maxPoolSize">1000</property>
<!-- C3P0 数据库连接池可以维护的 Statement 的个数 -->
<property name="maxStatements">20</property>
<!-- 每个连接同时可以使用的 Statement 对象的个数 -->
<property name="maxStatementsPerConnection">5</property>
</named-config>
</c3p0-config>
2.编写JDBCTools
package com.anqi.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class JDBCTools {
private static DataSource dataSource = null;
//数据库连接池只需要被初始化一次
static {
dataSource = new ComboPooledDataSource("helloc3p0");
}
public static Connection getConnection() throws Exception {
return dataSource.getConnection();
}
public static void releaseDb(ResultSet resultSet, Statement sta, Connection con) {
if(resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(sta != null) {
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con != null) {
try {
//数据库连接池的 connection 对象进行 close 时
//并不是真的进行关闭,而是把数据库连接归还到数据库连接池中
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3.DAO接口
package com.anqi.jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* 返回数据的 DAO 接口
* 里边定义好访问数据表的个各种方法
* 可供 JDBC 实现、JDBCUtils 实现等
* @param T:DAO 处理的实体类的类型
*/
public interface DAO<T> {
/**
* 批量处理的方法
* @param con
* @param sql
* @param args:填充占位符的 Object [] 类型的可变参数
*/
void batch(Connection con, String sql, Object[] ...args);
/**
* 返回一个具体的值,比如总人数,平均工资,某人的姓名等
* @param con
* @param sql
* @param args
* @return
*/
<E> E getForValue(Connection con, String sql, Object ...args);
/**
* 返回 T 的一个请求
* @param con
* @param sql
* @param args
* @return
*/
List<T> getForList(Connection con, String sql, Object ...args);
/**
* 返回一个 T 的对象
* @param con
* @param sql
* @param args
* @return
* @throws SQLException
*/
T get(Connection con, String sql, Object ...args) throws SQLException;
/**
* INSERT,UPDATE,DELETE
* @param con:数据库连接
* @param sql:sql 语句
* @param args:填充占位符的参数
*/
void update(Connection con, String sql, Object ... args);
}
4.JDBC实现DAO接口
package com.anqi.jdbc;
import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
/**
* 使用 QueryRunner 提供其具体实现
* @param <T> 子类传入的泛型类型
*/
public class JdbcDaoImp<T> implements DAO<T>{
private QueryRunner queryRunner = null;
private Class<T> type;
public JdbcDaoImp() {
queryRunner = new QueryRunner();
type =(Class<T>) ((ParameterizedType)getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
public void batch(Connection con, String sql, Object[]... args) {
}
public Object getForValue(Connection con, String sql, Object... args) {
return null;
}
public List getForList(Connection con, String sql, Object... args) {
return null;
}
public T get(Connection con, String sql, Object... args) throws SQLException {
return queryRunner.query(con, sql, new BeanHandler<>(type),args);
}
public void update(Connection con, String sql, Object... args) {
}
}
5.CustomerDao 可以再此处添加其他业务,也可以直接使用访问进行数据访问
package com.anqi.jdbc;
public class CustomerDao extends JdbcDaoImp<Customer>{
}