昨日の演習では、各演習でデータベースとの接続を確立し、完了したら切断する必要がありましたが、処理されるデータ量が特殊な場合、非常に時間がかかります。今日は、接続プールの使用法、接続プールへの接続の入れ方、および必要に応じて接続を取り出す方法を学習します。使用後に接続をプールに戻すことは、接続を切断することを意味しません。
データベース接続プールの基本的な考え方は、データベース接続用の「バッファー プール」を確立することです。データベース接続を確立する必要がある場合、あらかじめ一定数のコネクションをバッファプールに入れておくと、使用後に「バッファプール」から 1 つだけ取り出して元に戻すだけで済みます。
データベース接続プールは、初期化中に特定の数のデータベース接続を作成し、それらを接続プールに入れます。これらのデータベース接続の数は、データベース接続の最小数によって設定されます。これらのデータベース接続が使用されるかどうかに関係なく、接続プールには少なくともこの数の接続が常に保証されます。接続プール内のデータベース接続の最大数は、接続プールが占有できる最大接続数を制限します。アプリケーションによって接続プールから要求された接続数が最大接続数を超えると、これらの要求は接続プールに追加されます。待機列。
従来の開発におけるデータベース接続の問題を解決するために、データベース接続プール技術を使用できます。
データベース接続プールは、データベース接続の割り当て、管理、解放を担当します。これにより、アプリケーションはデータベース接続を再確立するのではなく、既存のデータベース接続を再利用できるようになります。
まず、DBCP 接続プール (無料のオープンソース接続プール) を使用します。まず、commons-dbcp-1.4.jar ファイルを現在のプロジェクトに配置し、環境を構成する必要があります (ビルドに追加)。パス)。プログラムを通じて DBCP 接続プールを使用する方法を学びましょう:
ここで前と同様に「dbcp.properties」ファイルを作成し、必要なパラメータをその中に入れる必要があります。その内容は次のとおりです (このファイルは配置されます)。現在のプロジェクトでは)、DBCP 接続プールはこのファイルを使用して mysql および oracle 接続プールの確立を完了できますが、一度に作成できるのは 1 つだけであり、もう 1 つはコメントする必要があります。
driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://127.0.0.1:3306/company
username = root
password = 123456
初期サイズ = 5
maxActive = 50
maxIdle = 10
#driverClassName = oracle.jdbc.driver.OracleDriver
#url = jdbc:oracle:thin:@127.0.0.1:1521:orcl
#username = scオット
#password = Tiger
package com.atguigu.jdbc; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import org.junit.Test; public class DBCPTest { @Test public void test2() throws Exception { Properties properties = new Properties(); properties.load(new FileInputStream("dbcp.properties")); DataSource dataSource = BasicDataSourceFactory.createDataSource(properties); System.out.println("inital:" + ((BasicDataSource)dataSource).getInitialSize()); System.out.println("getMaxActive:" + ((BasicDataSource)dataSource).getMaxActive()); System.out.println("getMaxIdle:" + ((BasicDataSource)dataSource).getMaxIdle()); Connection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); } }
次に、上で行ったように、より強力な接続プール、C3P0 (まだ無料でオープンソースの接続プール) について学習します。まず、commons-dbcp-1.4.jar ファイルを現在のプロジェクトに配置し、環境を構成する (ビルド パスに追加する) 必要があります。
DBCP 接続プールの使用方法を学習するプログラムは次のとおりです。
DBCP 接続プールと同様に、「c3p0-config.xml」ファイルを作成し、その中に必要なパラメーターを追加する必要があります。その内容は次のとおりです。 (このファイルは現在のプロジェクトの src ディレクトリに置かれます)
com.mysql.jdbc.Driver jdbc:mysql://127.0.0.1:3306/school root 123456 5 5 5 50 0 5 oracle.jdbc.driver.OracleDriver jdbc:mysql://127.0.0.1:3306/school root 123456
DBCP连接池使用这个文件可以完成mysql、oracle的连接池的建立,每次只能建立一个,但是另一个需要注释起来。因为我们是根据
package com.atguigu.jdbc; import java.beans.PropertyVetoException; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import org.junit.Test; import com.mchange.v2.c3p0.*; public class C3P0Test { @Test public void test1() throws PropertyVetoException, SQLException { DataSource dataSource = new ComboPooledDataSource("mysql-config"); // 它会默认自动去读取文件 System.out.println(dataSource); Connection connection = dataSource.getConnection(); System.out.println(connection); connection.close();// 把连接归还给连接池 DataSources.destroy(dataSource);// 完全释放池中所有连接,并销毁连接池!! } @Test public void test2() throws PropertyVetoException, SQLException { DataSource dataSource = new ComboPooledDataSource("oracle-config"); // 它会默认自动去读取文件 System.out.println(dataSource); Connection connection = dataSource.getConnection(); System.out.println(connection); connection.close();// 把连接归还给连接池 DataSources.destroy(dataSource);// 完全释放池中所有连接,并销毁连接池!! } }
学习了连接池之后,JdbcUtil工具类中的getConnection方法就可以应用,如下:
package com.atguigu.jdbc; import java.io.FileInputStream; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; import com.mchange.v2.c3p0.DataSources; /** * 预备工作 : * 1) 把要访问的数据库相关的驱动程序复制到项目中, 就是jar包 * 2) 配置项目属性, 把jar包导入到本项目的buildpath中 * @author Administrator * */ public class JdbcUtil { private static DataSource dataSource; // 声明静态属性对象引用. static { dataSource = new ComboPooledDataSource("mysql-config"); // 连接池对象只需要创建一次就可以了 } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); // 要想获取连接, 只需要从连接池中获取,用完以后, 再归还回来 } public static Connection getConnectionOld() throws IOException, ClassNotFoundException, SQLException { // 1) 读取配置文件 Properties properties = new Properties(); properties.load(new FileInputStream("jdbc.properties")); // 2) 获取配置文件中的必要的信息 String driverClass = properties.getProperty("driverClass"); String url = properties.getProperty("url"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); // 3) 注册驱动 , 加载驱动类 Class.forName(driverClass); // 4) 通过驱动管理器获取连接(需要url,用户,密码) return DriverManager.getConnection(url, user, password);// 暗含 new Socket(host,port), 认证,其他各种初始化操作 } //关闭连接 public static void close(Connection connection) { close(connection, null); } public static void close(Connection connection, Statement statement) { close(connection, statement, null); } public static void close(Connection connection, Statement statement, ResultSet resultSet) { if (resultSet != null) { try { resultSet.close(); } catch (Exception e) { e.printStackTrace(); } } if (statement != null) { try { statement.close(); } catch (Exception e) { e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (Exception e) { e.printStackTrace(); } } } //销毁连接池 public static void destroy() { try { DataSources.destroy(dataSource); } catch (SQLException e) { e.printStackTrace(); } } }
将常用的操作数据库的JDBC的类和方法集合在一起,就是DBUtils.JDBC。提供供我们使用的工具类QueryRunner来执行操作。
在使用之前我们仍然需要将commons-dbutils-1.3.jar添加到当前工程下,并添加到path路径。
package com.atguigu.jdbc; import java.sql.Connection; import java.sql.SQLException; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.ArrayListHandler; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import org.junit.Test; public class QueryRunnerTest { // 使用我们自定义工具实现表的创建 @Test public void test1() throws SQLException { QueryRunner qr = new QueryRunner(); Connection connection = JdbcUtil.getConnection(); qr.update(connection, "create table test2(aa int, bb varchar(10))"); JdbcUtil.close(connection); } // 使用我们自定义工具向表中插入一条记录 @Test public void test2() throws SQLException { QueryRunner qr = new QueryRunner(); Connection connection = JdbcUtil.getConnection(); int rows = qr.update(connection, "insert into test2(aa, bb) values(?,?)", 10, "xxx"); System.out.println(rows + " rows"); JdbcUtil.close(connection); } // 使用DBUtils.JDBC接口中提供的方法对departments表进行查询,把结果集中的所有记录转换为department对象集合并存入List集合中,然后遍历输出对象 @Test public void test3() throws SQLException { //query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) String sql = "select * from departments where department_id > ?"; QueryRunner qr = new QueryRunner(); Connection connection = JdbcUtil.getConnection(); BeanListHandler<Department> rsh = new BeanListHandler<Department>(Department.class); // 把结果集中的所有记录转换为对象集合 List<Department> list = qr.query(connection, sql, rsh, 20); for (Department department : list) { System.out.println(department); } } // 使用DBUtils.JDBC接口中提供的方法对departments表进行查询,把结果集中的一条记录转换为department实体对象,然后输出对象 @Test public void test4() throws SQLException { String sql = "select * from departments where department_id = ?"; QueryRunner qr = new QueryRunner(); Connection connection = JdbcUtil.getConnection(); BeanHandler<Department> rsh = new BeanHandler<Department>(Department.class); // 把结果集中的一条记录转换为实体对象 Department objDepartment = qr.query(connection, sql, rsh, 20); System.out.println(objDepartment); } // 使用DBUtils.JDBC接口中提供的方法对departments表进行查询,将每一条记录存入集合中,然后遍历输出每一个数据 @Test public void test5() throws SQLException { String sql = "select * from employees"; QueryRunner qr = new QueryRunner(); Connection connection = JdbcUtil.getConnection(); ArrayListHandler rsh = new ArrayListHandler(); List<Object[]> list = qr.query(connection, sql, rsh); for (Object[] objects : list) { for (int i = 0; i < objects.length; i++) { System.out.print(objects[i] + "\t"); } System.out.println(); } } // 使用DBUtils.JDBC接口中提供的方法对departments表进行查询,将查询到的一个数据输出 @Test public void test6 () throws SQLException { String sql = "select count(*) from world.country"; QueryRunner qr = new QueryRunner(); Connection connection = JdbcUtil.getConnection(); ScalarHandler rsh = new ScalarHandler(); Object singleValue = qr.query(connection, sql, rsh); System.out.println(singleValue); } @Test public void test7() throws Exception { QueryRunner qr = new QueryRunner(); List<Object> list = qr.query(JdbcUtil.getConnection(), "select * from student", new ColumnListHandler(1)); for (Object object : list) { System.out.println(object); } } //MapHandler把第一行数据封装到Map集合中, 列名作为键, 对应值作为值 @Test public void test8() throws Exception { QueryRunner qr = new QueryRunner(); Map<String, Object> map = qr.query(JdbcUtil.getConnection(), "select * from student", new MapHandler()); Set<String> keys = map.keySet(); for (String key : keys) { Object value = map.get(key); System.out.println(key + " -------- " + value); } } //MapListHandler把一行数据封装到Map集合中, 并把所有行生成的Map再放入一个List集合 @Test public void test9() throws Exception { QueryRunner qr = new QueryRunner(); List<Map<String, Object>> list = qr.query(JdbcUtil.getConnection(), "select * from student", new MapListHandler()); for (Map<String, Object> map2 : list) { Set<String> keys = map2.keySet(); for (String key : keys) { Object value = map2.get(key); System.out.println(key + " -------- " + value); } System.out.println(); } } }
到这里就可以统一整理一下自己定义的JdbcUtil工具类、CommonUtil工具类,使自定义的工具类能达到JDButi.JDBC相同的功能,如下:
JdbcUtils.java
package com.atguigu.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; import com.mchange.v2.c3p0.DataSources; public class JdbcUtil { private static DataSource dataSource; static { dataSource = new ComboPooledDataSource("config1"); // 它必须依赖文件src/c3p0-config.xml } // 获取c3p0连接池的连接 public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } public static void close(Connection connection) { close(connection, null); } public static void close(Connection connection, Statement statement) { close(connection, statement, null); } public static void close(Connection connection, Statement statement, ResultSet resultSet) { if (resultSet != null) { try { resultSet.close(); } catch (Exception e) { e.printStackTrace(); } } if (statement != null) { try { statement.close(); } catch (Exception e) { e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (Exception e) { e.printStackTrace(); } } } public static void destroy() { try { DataSources.destroy(dataSource); } catch (SQLException e) { e.printStackTrace(); } } }
CommonUtil.java
package com.atguigu.jdbc; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class CommonUtil { /** * 把结果集中的每一行都放入Object对象数组中, 再把所有的Object对象数组放入一个List集合中. * @throws SQLException */ public static List<Object[]> query(Connection connection, String sql, Object... values) throws SQLException { PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { preparedStatement = connection.prepareStatement(sql); fillArguments(preparedStatement, values); resultSet = preparedStatement.executeQuery(); List<Object[]> list = new ArrayList<Object[]>(); int cols = resultSet.getMetaData().getColumnCount(); while (resultSet.next()) { Object[] dataRow = new Object[cols]; for (int i = 0; i < dataRow.length; i++) { dataRow[i] = resultSet.getObject(i + 1); } list.add(dataRow); } return list; } finally { JdbcUtil.close(null, preparedStatement, resultSet); } } /** * 把结果集中的第一行数据,全放入一个对象数组中 * @throws SQLException */ public static Object[] queryValueArray(Connection connection, String sql, Object... values) throws SQLException { PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { preparedStatement = connection.prepareStatement(sql); fillArguments(preparedStatement, values); resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { Object[] dataRow = new Object[resultSet.getMetaData().getColumnCount()]; for (int i = 0; i < dataRow.length; i++) { dataRow[i] = resultSet.getObject(i + 1); } return dataRow; } else { return null; } } finally { JdbcUtil.close(null, preparedStatement, resultSet); } } /** * 从结果集中获取第一行的第一列 * @throws SQLException */ public static Object queryValue(Connection connection, String sql, Object... values) throws SQLException { PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { preparedStatement = connection.prepareStatement(sql); fillArguments(preparedStatement, values); resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { return resultSet.getObject(1); } else { return null; } } finally { JdbcUtil.close(null, preparedStatement, resultSet); } } /** * 把结果集中第一行转换为对象返回 * @throws SQLException * @throws SecurityException * @throws NoSuchFieldException * @throws IllegalAccessException * @throws InstantiationException */ public static <T> T queryBean(Connection connection, String sql, Class<T> clazz, Object... values) throws SQLException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException { PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { preparedStatement = connection.prepareStatement(sql); fillArguments(preparedStatement, values); resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { T t = clazz.newInstance(); ResultSetMetaData metaData = resultSet.getMetaData(); int cols = metaData.getColumnCount(); for (int i = 0; i < cols; i++) { String label = metaData.getColumnLabel(i + 1); Object value = resultSet.getObject(label); Field field = clazz.getDeclaredField(label); field.setAccessible(true); field.set(t, value); } return t; } else { return null; } } finally { JdbcUtil.close(null, preparedStatement, resultSet); } } /** * 把结果集的所有记录都封装成对象,并把所有对象放在一个List集合中 * @throws SQLException * @throws IllegalAccessException * @throws InstantiationException * @throws SecurityException * @throws NoSuchFieldException */ public static <T> List<T> query(Connection connection, String sql, Class<T> clazz, Object... values) throws SQLException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException { PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { preparedStatement = connection.prepareStatement(sql); fillArguments(preparedStatement, values); resultSet = preparedStatement.executeQuery(); List<T> list = new ArrayList<T>(); ResultSetMetaData metaData = resultSet.getMetaData(); int cols = metaData.getColumnCount(); while (resultSet.next()) { T t = clazz.newInstance(); for (int i = 0; i < cols; i++) { String label = metaData.getColumnLabel(i + 1); Object value = resultSet.getObject(label); if (value != null) { Field field = clazz.getDeclaredField(label); field.setAccessible(true); field.set(t, value); } } list.add(t); } return list; } finally { JdbcUtil.close(null, preparedStatement, resultSet); } } /** * 通用更新操作 * @throws SQLException */ public static int update(Connection connection, String sql, Object... values) throws SQLException { PreparedStatement preparedStatement = null; try { preparedStatement = connection.prepareStatement(sql); fillArguments(preparedStatement, values); return preparedStatement.executeUpdate(); } finally { JdbcUtil.close(null, preparedStatement); } } public static void fillArguments(PreparedStatement preparedStatement, Object... values) throws SQLException { for (int i = 0; i < values.length; i++) { preparedStatement.setObject(i + 1, values[i]); } } }
综合之前学习过的知识,在这里创建一个BaseDAO
package com.atguigu.jdbc; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; 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; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; public class BaseDAO<T>{ protected Class<T> clazz; // T泛型究竟是什么类型, 用类模板对象来描述 protected QueryRunner qr = new QueryRunner(); // 用于执行通用查询和更新的工具类对象 protected Connection connection; // 数据库连接 protected String tableName; // 涉及到的表,需要通过构造器初始化赋值 public JdbcDAO(String tableName) { // 以下代码的执行者是子类对象,所以this.getClass是获取子类的类模板对象 Type type = this.getClass().getGenericSuperclass(); // JdbcDAO<Teacher> if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType)type;//JdbcDAO<Teacher> Type[] types = parameterizedType.getActualTypeArguments(); clazz = (Class<T>)types[0]; } else { clazz = (Class<T>)Object.class; } // 获取一个连接供所有方法使用 try { connection = JdbcUtil.getConnection(); } catch (SQLException e) { e.printStackTrace(); } this.tableName = tableName; } //获得记录中具体的一个数据 public Object getValue(String sql, Object... values) { try { return qr.query(connection, sql, new ScalarHandler(), values); } catch (SQLException e) { e.printStackTrace(); } return null; } //获得一行数据并封装成javabean对象 public T get(String sql, Object... values) { try { return qr.query(connection, sql, new BeanHandler<T>(clazz), values); } catch (SQLException e) { e.printStackTrace(); } return null; } //获得多行记录,封装成javabean对象,保存在list集合中 public List<T> getList(String sql, Object... values) { try { return qr.query(connection, sql, new BeanListHandler<T>(clazz), values); } catch (SQLException e) { e.printStackTrace(); } return null; } //获得所有记录,封装成javabean对象,保存在list集合中 public List<T> getAll() { return getList("select * from " + tableName); } //根据id获取某一条记录,并封装成javabean对象返回 public T getById(int id) { return get("select * from " + tableName + " where id = ?", id); } //根据id删除某一条记录,删除成功返回ture,失败返回false public boolean deleteById(int id) { int rows = update("delete from " + tableName + " where id = ?", id); if (rows > 0) { return true; } return false; } //通用的更新操作 public int update(String sql, Object... values) { try { return qr.update(connection, sql, values); } catch (SQLException e) { e.printStackTrace(); } return 0; } //关闭连接 public void close() { JdbcUtil.close(connection); } }
以上就是JDBC-数据连接池的使用 的内容,更多相关内容请关注PHP中文网(www.php.cn)!