JDBC中的 数据库连接池
![](https://i-blog.csdnimg.cn/blog_migrate/3c731c8766501d529b5262e854f8356a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bfbfd2707d3eb64c497e375c5e2c49a4.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a2534949b5935ed2603f735a1deff34b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c408dec5a8d17ed437d75bd4cbae6ed8.png)
![](https://i-blog.csdnimg.cn/blog_migrate/80a46724ebb5c1abf6bb13759450de64.png)
![](https://i-blog.csdnimg.cn/blog_migrate/153d0e8a8eaf5d9a57e6f5d80552102e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/67bfa1ee56000833d1fe9695c31f1ea3.png)
//C3P0 数据库连接池,方式一
@Test
public void test1() throws Exception{
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
ds.setUser("root");
ds.setPassword("123456");
ds.setMaxPoolSize(10);
ds.setAcquireIncrement(3);
Connection conn = ds.getConnection();
System.out.println(conn);
conn.close();
}
//C3P0 数据库连接池,方式二
@Test
public void test2() throws Exception{
DataSource ds = new ComboPooledDataSource("helloc3p0");
Connection conn = ds.getConnection();
System.out.println(conn);
}
代码段二中采用c3p0数据库连接池的是加载配置文件的方式创建数据库连接池的,配置文件名字必须统一叫做c3p0-config.xml,还要加载.jar文件,方法如下:
c3p0-config.xml的内容:
<c3p0-config>
<named-config name="helloc3p0">
<!-- 四个连接字符串 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/gome</property>
<property name="user">root</property>
<property name="password">123456</property>
<!-- 若连接池满了,一次增上的连接数 -->
<property name="acquireIncrement">5</property>
<!-- 初始连接池大小 -->
<property name="initialPoolSize">10</property>
<!-- 连接池中最小连接数量 -->
<property name="minPoolSize">5</property>
<!-- 连接池中最大连接数量 -->
<property name="maxPoolSize">10</property>
<!-- 连接池中最多管理的 Statment 的个数 -->
<property name="maxStatements">5</property>
<!-- 连接池中每个连接管理的 Statement 的个数 -->
<property name="maxStatementsPerConnection">5</property>
</named-config>
</c3p0-config>
//DBCP 数据库连接池,方式一:
@Test
public void test3() throws Exception{
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setUrl("jdbc:mysql://localhost:3306/test");
bds.setUsername("root");
bds.setPassword("123456");
bds.setInitialSize(10);
bds.setMaxActive(10);
Connection conn = bds.getConnection();
System.out.println(conn);
}
//DBCP 数据库连接池,方式二:
@Test
public void test4() throws Exception{
Properties props = new Properties();
props.load(this.getClass().getClassLoader().getResourceAsStream("com/gome/day1/properties"));
DataSource ds = BasicDataSourceFactory.createDataSource(props);
Connection conn = ds.getConnection();
System.out.println(conn);
}
上边代码块二的方式是DBCP数据库连接池加载资源文件的方式,先加载两个.jar文件,在添加资源文件。properties详情如下:
需要注意的是,使用类加载器的方式加载资源文件,资源文件交放在包下与代码同一级别,并且资源文件中key的名字要严格按照方法中的名字取,不然无法成功。
事务的commit与rollback
下列程序在两次更新数据库表中数据的中间模拟故障,用来测试commit与rollback的作用:
public class TestTransaction {
// 模拟:
@Test
public void test1(){
Connection conn = null;
try {
conn = JDBCUtils.getConnection();
conn.setAutoCommit(false); //取消自动提交,事务开启
String sql1 = "update user_table set balance = balance - 100 where user = ?";
update(conn, sql1, "AA");
//模拟故障
// int num = 10 / 0;
String sql2 = "update user_table set balance = balance + 100 where user = ?";
update(conn, sql2, "BB");
conn.commit(); //提交
} catch (Exception e) {
e.printStackTrace();
//回滚
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
JDBCUtils.close(null, null, conn);
}
}
/*
* 考虑事务的通用查询
*/
public <T> T get(Connection conn, String sql, Class<T> clazz, Object... args) {
T t = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
// 获取当前结果集的元数据
ResultSetMetaData rsmd = rs.getMetaData();
// 获取结果集的列数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
t = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {
// 获取列名
String columnName = rsmd.getColumnLabel(i + 1);
// 根据列名获取对应列的数据
Object columnValue = rs.getObject(columnName);
Field field = clazz.getDeclaredField(columnName);// 注意:必须保证结果集中列名(别名),与属性名称保持一致!!!!!
field.setAccessible(true);// 忽略访问权限
field.set(t, columnValue);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.close(rs, ps, null);
}
return t;
}
/*
* 考虑事务的,通用的增、删、改方法,适用于任何表
*/
public int update(Connection conn, String sql, Object... args) {
// 2. 获取 PreparedStatement , 用于发送 SQL
PreparedStatement ps = null;
// 4. 执行 SQL
int row = 0;
try {
ps = conn.prepareStatement(sql);
// 3. 填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
row = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 5. 关闭连接
JDBCUtils.close(ps, null);
}
return row;
}
}
DBUtils工具类的使用
public class TestDBUtils {
private QueryRunner qr = new QueryRunner();
//获取特殊某个值
@Test
public void test6(){
Connection conn = null;
try {
conn = JDBCUtils.getConnectionForC3P0();
String sql = "select count(*) from customers";
ResultSetHandler<Object> rsh = new ScalarHandler();
Object obj = qr.query(conn, sql, rsh);
System.out.println(obj);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(null, null, conn);
}
}
//查询多个对象组成的存入 Map 集合, List 集合
@Test
public void test5(){
Connection conn = null;
try {
conn = JDBCUtils.getConnectionForC3P0();
String sql = "select id, name, email, birth from customers where id < ?";
ResultSetHandler<List<Map<String,Object>>> rsh = new MapListHandler();
List<Map<String,Object>> list = qr.query(conn, sql, rsh, 21);
for (Map<String, Object> map : list) {
Set<Entry<String,Object>> entrySet = map.entrySet();
for (Entry<String, Object> entry : entrySet) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
System.out.println("-----------------------------------------------------------------");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(null, null, conn);
}
}
//查询多个对象组成的 List 集合
@Test
public void test4(){
Connection conn = null;
try {
conn = JDBCUtils.getConnectionForC3P0();
String sql = "select id, name, email, birth from customers where id < ?";
ResultSetHandler<List<Customer>> rsh = new BeanListHandler<Customer>(Customer.class);
List<Customer> list = qr.query(conn, sql, rsh, 21);
for (Customer customer : list) {
System.out.println(customer);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(null, null, conn);
}
}
//查询一个对象
@Test
public void test3(){
Connection conn = null;
try {
conn = JDBCUtils.getConnectionForC3P0();
String sql = "select id, name, email, birth from customers where id = ?";
ResultSetHandler<Customer> rsh = new BeanHandler<Customer>(Customer.class);
Customer cust = qr.query(conn, sql, rsh, 20);
System.out.println(cust);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(null, null, conn);
}
}
@Test
public void test2(){
ResultSetHandler<List<Customer>> rsh = new ResultSetHandler<List<Customer>>() {
@Override
public List<Customer> handle(ResultSet arg0) throws SQLException {
return null;
}
};
}
//添加数据
@Test
public void test1(){
Connection conn = null;
try {
conn = JDBCUtils.getConnectionForC3P0();
String sql = "insert into customers(id, name, email, birth) values(?,?,?,?)";
int row = qr.update(conn, sql, 20, "陈晨", "chenchen@abc.com", "1999-9-9");
System.out.println("已影响 " + row + " 行");
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(null, null, conn);
}
}
}