澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

行使连接池前后连接数据库的对峙统风流倜傥

2019-10-30 作者:数据库网络   |   浏览(156)

首先,为什么使用JDBC?

JDBC

今日任务

  • 使用JDBC完成对分类表的CRUD的操作(JDBC的回顾)
  • 使用DBCP,C3P0连接池完成基本数据库的操作(抽取工具类)
  • 能够使用DBUtils完成CRUD的操作

 

教学导航

教学目标

掌握DBCP和C3P0连接池的使用并掌握连接池的原理.

能够使用DBUtils完成基本的CRUD的操作

教学方法

案例驱动法

 

        JDBC是指java数据库连接,是面向关系型数据库的,它实际就是一个JAVA封装的API,我们采用Java语言执行sql语句,对(各种)数据库操作,具有跨平台性。不管是什么关         系数据库,我们都可以通过jdbc实现数据库的连接和操作。

1.1 使用JDBC完成对于分类的CRUD的操作-回顾JDBC

 

1.数据库的连接

 

 

[java] view plain copy

 

  1. /** 
  2.      * DriverManager 是驱动的管理类.  
  3.      * 1). 可以通过重载的 getConnection() 方法获取数据库连接. 较为方便 
  4.      * 2). 可以同时管理多个驱动程序: 若注册了多个数据库连接, 则调用 getConnection() 
  5.      * 方法时传入的参数不同, 即返回不同的数据库连接。  
  6.      * @throws Exception  
  7.      */  
  8.   
  9.   
  10.   
  11. @Test  
  12.     public void testGetConnection2() throws Exception{  
  13.         System.out.println(getConnection2());   
  14.     }  
  15.       
  16.     public Connection getConnection2() throws Exception{  
  17.         //1. 准备连接数据库的 4 个字符串.   
  18.         //1). 创建 Properties 对象  
  19.         Properties properties = new Properties();  
  20.           
  21.         //2). 获取 jdbc.properties 对应的输入流  
  22.         InputStream in =   
  23.                 this.getClass().getClassLoader().getResourceAsStream("jdbc.properties");  
  24.           
  25.         //3). 加载 2) 对应的输入流  
  26.         properties.load(in);  
  27.           
  28.         //4). 具体决定 user, password 等4 个字符串.   
  29.         String user = properties.getProperty("user");  
  30.         String password = properties.getProperty("password");  
  31.         String jdbcUrl = properties.getProperty("jdbcUrl");  
  32.         String driver = properties.getProperty("driver");  
  33.           
  34.         //2. 加载数据库驱动程序(对应的 Driver 实现类中有注册驱动的静态代码块.)  
  35.         Class.forName(driver);  
  36.           
  37.         //3. 通过 DriverManager 的 getConnection() 方法获取数据库连接.   
  38.         return DriverManager.getConnection(jdbcUrl, user, password);  
  39.     }  

 

2.statement 和prepareStatement

 

 

[java] view plain copy

 

  1. @Test  
  2. public void testPreparedStatement() {  
  3.     Connection connection = null;  
  4.     PreparedStatement preparedStatement = null;  
  5.   
  6.     try {  
  7.         connection = JDBCTools.getConnection();  
  8.         String sql = "INSERT INTO customers (name, email, birth) "  
  9.                   "VALUES(?,?,?)";  
  10.   
  11.         preparedStatement = connection.prepareStatement(sql);  
  12.         preparedStatement.setString(1, "ATGUIGU");  
  13.         preparedStatement.setString(2, "simpleit@163.com");  
  14.         preparedStatement.setDate(3,  
  15.                 new Date(new java.util.Date().getTime()));  
  16.   
  17.         preparedStatement.executeUpdate();  
  18.     } catch (Exception e) {  
  19.         e.printStackTrace();  
  20.     } finally {  
  21.         JDBCTools.releaseDB(null, preparedStatement, connection);  
  22.     }  
  23. }  

 

 

[java] view plain copy

 

  1. /** 
  2.  * SQL 注入. 
  3.  */  
  4. @Test  
  5. public void testSQLInjection() {  
  6.     String username = "a' OR PASSWORD = ";  
  7.     String password = " OR '1'='1";  
  8.   
  9.     String sql = "SELECT * FROM users WHERE username = '"   username  
  10.               "' AND "   "password = '"   password   "'";  
  11.   
  12.     System.out.println(sql);  
  13.   
  14.     Connection connection = null;  
  15.     Statement statement = null;  
  16.     ResultSet resultSet = null;  
  17.   
  18.     try {  
  19.         connection = JDBCTools.getConnection();  
  20.         statement = connection.createStatement();  
  21.         resultSet = statement.executeQuery(sql);  
  22.   
  23.         if (resultSet.next()) {  
  24.             System.out.println("登录成功!");  
  25.         } else {  
  26.             System.out.println("用户名和密码不匹配或用户名不存在. ");  
  27.         }  
  28.   
  29.     } catch (Exception e) {  
  30.         e.printStackTrace();  
  31.     } finally {  
  32.         JDBCTools.releaseDB(resultSet, statement, connection);  
  33.     }  
  34. }  

 

 

 

3.JDBCTools

 

 

[java] view plain copy

 

  1. package com.atguigu.jdbc;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.sql.Connection;  
  6. import java.sql.DriverManager;  
  7. import java.sql.PreparedStatement;  
  8. import java.sql.ResultSet;  
  9. import java.sql.SQLException;  
  10. import java.sql.Statement;  
  11. import java.util.Properties;  
  12.   
  13. public class JDBCTools {  
  14.   
  15.     /** 
  16.      * 执行 SQL 语句, 使用 PreparedStatement 
  17.      * @param sql 
  18.      * @param args: 填写 SQL 占位符的可变参数 
  19.      */  
  20.     public static void update(String sql, Object ... args){  
  21.         Connection connection = null;  
  22.         PreparedStatement preparedStatement = null;  
  23.           
  24.         try {  
  25.             connection = JDBCTools.getConnection();  
  26.             preparedStatement = connection.prepareStatement(sql);  
  27.               
  28.             for(int i = 0; i < args.length; i ){  
  29.                 preparedStatement.setObject(i   1, args[i]);  
  30.             }  
  31.               
  32.             preparedStatement.executeUpdate();  
  33.               
  34.         } catch (Exception e) {  
  35.             e.printStackTrace();  
  36.         } finally{  
  37.             JDBCTools.releaseDB(null, preparedStatement, connection);  
  38.         }  
  39.     }  
  40.       
  41.     /** 
  42.      * 执行 SQL 的方法 
  43.      *  
  44.      * @param sql: insert, update 或 delete。 而不包含 select 
  45.      */  
  46.     public static void update(String sql) {  
  47.         Connection connection = null;  
  48.         Statement statement = null;  
  49.   
  50.         try {  
  51.             // 1. 获取数据库连接  
  52.             connection = getConnection();  
  53.   
  54.             // 2. 调用 Connection 对象的 createStatement() 方法获取 Statement 对象  
  55.             statement = connection.createStatement();  
  56.   
  57.             // 4. 发送 SQL 语句: 调用 Statement 对象的 executeUpdate(sql) 方法  
  58.             statement.executeUpdate(sql);  
  59.   
  60.         } catch (Exception e) {  
  61.             e.printStackTrace();  
  62.         } finally {  
  63.             // 5. 关闭数据库资源: 由里向外关闭.  
  64.             releaseDB(null, statement, connection);  
  65.         }  
  66.     }  
  67.   
  68.     /** 
  69.      * 释放数据库资源的方法 
  70.      *  
  71.      * @param resultSet 
  72.      * @param statement 
  73.      * @param connection 
  74.      */  
  75.     public static void releaseDB(ResultSet resultSet, Statement statement,  
  76.             Connection connection) {  
  77.   
  78.         if (resultSet != null) {  
  79.             try {  
  80.                 resultSet.close();  
  81.             } catch (SQLException e) {  
  82.                 e.printStackTrace();  
  83.             }  
  84.         }  
  85.   
  86.         if (statement != null) {  
  87.             try {  
  88.                 statement.close();  
  89.             } catch (SQLException e) {  
  90.                 e.printStackTrace();  
  91.             }  
  92.         }  
  93.   
  94.         if (connection != null) {  
  95.             try {  
  96.                 connection.close();  
  97.             } catch (SQLException e) {  
  98.                 e.printStackTrace();  
  99.             }  
  100.         }  
  101.   
  102.     }  
  103.   
  104.     /** 
  105.      * 获取数据库连接的方法 
  106.      */  
  107.     public static Connection getConnection() throws IOException,  
  108.             ClassNotFoundException, SQLException {  
  109.         // 0. 读取 jdbc.properties  
  110.         /** 
  111.          * 1). 属性文件对应 Java 中的 Properties 类 2). 可以使用类加载器加载 bin 目录(类路径下)的文件 
  112.          */  
  113.         Properties properties = new Properties();  
  114.         InputStream inStream = ReviewTest.class.getClassLoader()  
  115.                 .getResourceAsStream("jdbc.properties");  
  116.         properties.load(inStream);  
  117.   
  118.         // 1. 准备获取连接的 4 个字符串: user, password, jdbcUrl, driverClass  
  119.         String user = properties.getProperty("user");  
  120.         String password = properties.getProperty("password");  
  121.         String jdbcUrl = properties.getProperty("jdbcUrl");  
  122.         String driverClass = properties.getProperty("driverClass");  
  123.   
  124.         // 2. 加载驱动: Class.forName(driverClass)  
  125.         Class.forName(driverClass);  
  126.   
  127.         // 3. 调用  
  128.         // DriverManager.getConnection(jdbcUrl, user, password)  
  129.         // 获取数据库连接  
  130.         Connection connection = DriverManager.getConnection(jdbcUrl, user,  
  131.                 password);  
  132.         return connection;  
  133.     }  
  134.   
  135. }  

 

 

 

 

 

 

4.DAO

 

 

 

 

 

[java] view plain copy

 

  1. package com.atguigu.jdbc;  
  2.   
  3. import java.lang.reflect.InvocationTargetException;  
  4. import java.sql.Connection;  
  5. import java.sql.PreparedStatement;  
  6. import java.sql.ResultSet;  
  7. import java.sql.ResultSetMetaData;  
  8. import java.sql.SQLException;  
  9. import java.util.ArrayList;  
  10. import java.util.HashMap;  
  11. import java.util.List;  
  12. import java.util.Map;  
  13.   
  14. import org.apache.commons.beanutils.BeanUtils;  
  15.   
  16. public class DAO {  
  17.   
  18.     // INSERT, UPDATE, DELETE 操作都可以包含在其中  
  19.     public void update(String sql, Object... args) {  
  20.         Connection connection = null;  
  21.         PreparedStatement preparedStatement = null;  
  22.   
  23.         try {  
  24.             connection = JDBCTools.getConnection();  
  25.             preparedStatement = connection.prepareStatement(sql);  
  26.   
  27.             for (int i = 0; i < args.length; i ) {  
  28.                 preparedStatement.setObject(i   1, args[i]);  
  29.             }  
  30.   
  31.             preparedStatement.executeUpdate();  
  32.         } catch (Exception e) {  
  33.             e.printStackTrace();  
  34.         } finally {  
  35.             JDBCTools.releaseDB(null, preparedStatement, connection);  
  36.         }  
  37.     }  
  38.   
  39.     // 查询一条记录, 返回对应的对象  
  40.     public <T> T get(Class<T> clazz, String sql, Object... args) {  
  41.         List<T> result = getForList(clazz, sql, args);  
  42.         if(result.size() > 0){  
  43.             return result.get(0);  
  44.         }  
  45.           
  46.         return null;  
  47.     }  
  48.   
  49.     /** 
  50.      * 传入 SQL 语句和 Class 对象, 返回 SQL 语句查询到的记录对应的 Class 类的对象的集合 
  51.      * @param clazz: 对象的类型 
  52.      * @param sql: SQL 语句 
  53.      * @param args: 填充 SQL 语句的占位符的可变参数.  
  54.      * @return 
  55.      */  
  56.     public <T> List<T> getForList(Class<T> clazz,   
  57.             String sql, Object... args) {  
  58.   
  59.         List<T> list = new ArrayList<>();  
  60.   
  61.         Connection connection = null;  
  62.         PreparedStatement preparedStatement = null;  
  63.         ResultSet resultSet = null;  
  64.   
  65.         try {  
  66.             //1. 得到结果集  
  67.             connection = JDBCTools.getConnection();  
  68.             preparedStatement = connection.prepareStatement(sql);  
  69.   
  70.             for (int i = 0; i < args.length; i ) {  
  71.                 preparedStatement.setObject(i   1, args[i]);  
  72.             }  
  73.   
  74.             resultSet = preparedStatement.executeQuery();  
  75.               
  76.             //2. 处理结果集, 得到 Map 的 List, 其中一个 Map 对象  
  77.             //就是一条记录. Map 的 key 为 reusltSet 中列的别名, Map 的 value  
  78.             //为列的值.   
  79.             List<Map<String, Object>> values =   
  80.                     handleResultSetToMapList(resultSet);  
  81.               
  82.             //3. 把 Map 的 List 转为 clazz 对应的 List  
  83.             //其中 Map 的 key 即为 clazz 对应的对象的 propertyName,   
  84.             //而 Map 的 value 即为 clazz 对应的对象的 propertyValue  
  85.             list = transfterMapListToBeanList(clazz, values);  
  86.   
  87.         } catch (Exception e) {  
  88.             e.printStackTrace();  
  89.         } finally {  
  90.             JDBCTools.releaseDB(resultSet, preparedStatement, connection);  
  91.         }  
  92.   
  93.         return list;  
  94.     }  
  95.   
  96.     public <T> List<T> transfterMapListToBeanList(Class<T> clazz,  
  97.             List<Map<String, Object>> values) throws InstantiationException,  
  98.             IllegalAccessException, InvocationTargetException {  
  99.   
  100.         List<T> result = new ArrayList<>();  
  101.   
  102.         T bean = null;  
  103.   
  104.         if (values.size() > 0) {  
  105.             for (Map<String, Object> m : values) {  
  106.                 bean = clazz.newInstance();  
  107.                 for (Map.Entry<String, Object> entry : m.entrySet()) {  
  108.                     String propertyName = entry.getKey();  
  109.                     Object value = entry.getValue();  
  110.   
  111.                     BeanUtils.setProperty(bean, propertyName, value);  
  112.                 }  
  113.                 // 13. 把 Object 对象放入到 list 中.  
  114.                 result.add(bean);  
  115.             }  
  116.         }  
  117.   
  118.         return result;  
  119.     }  
  120.   
  121.     /** 
  122.      * 处理结果集, 得到 Map 的一个 List, 其中一个 Map 对象对应一条记录 
  123.      *  
  124.      * @param resultSet 
  125.      * @return 
  126.      * @throws SQLException 
  127.      */  
  128.     public List<Map<String, Object>> handleResultSetToMapList(  
  129.             ResultSet resultSet) throws SQLException {  
  130.         // 5. 准备一个 List<Map<String, Object>>:  
  131.         // 键: 存放列的别名, 值: 存放列的值. 其中一个 Map 对象对应着一条记录  
  132.         List<Map<String, Object>> values = new ArrayList<>();  
  133.   
  134.         List<String> columnLabels = getColumnLabels(resultSet);  
  135.         Map<String, Object> map = null;  
  136.   
  137.         // 7. 处理 ResultSet, 使用 while 循环  
  138.         while (resultSet.next()) {  
  139.             map = new HashMap<>();  
  140.   
  141.             for (String columnLabel : columnLabels) {  
  142.                 Object value = resultSet.getObject(columnLabel);  
  143.                 map.put(columnLabel, value);  
  144.             }  
  145.   
  146.             // 11. 把一条记录的一个 Map 对象放入 5 准备的 List 中  
  147.             values.add(map);  
  148.         }  
  149.         return values;  
  150.     }  
  151.   
  152.     /** 
  153.      * 获取结果集的 ColumnLabel 对应的 List 
  154.      *  
  155.      * @param rs 
  156.      * @return 
  157.      * @throws SQLException 
  158.      */  
  159.     private List<String> getColumnLabels(ResultSet rs) throws SQLException {  
  160.         List<String> labels = new ArrayList<>();  
  161.   
  162.         ResultSetMetaData rsmd = rs.getMetaData();  
  163.         for (int i = 0; i < rsmd.getColumnCount(); i ) {  
  164.             labels.add(rsmd.getColumnLabel(i   1));  
  165.         }  
  166.   
  167.         return labels;  
  168.     }  
  169.   
  170.     // 返回某条记录的某一个字段的值 或 一个统计的值(一共有多少条记录等.)  
  171.     public <E> E getForValue(String sql, Object... args) {  
  172.           
  173.         //1. 得到结果集: 该结果集应该只有一行, 且只有一列  
  174.         Connection connection = null;  
  175.         PreparedStatement preparedStatement = null;  
  176.         ResultSet resultSet = null;  
  177.   
  178.         try {  
  179.             //1. 得到结果集  
  180.             connection = JDBCTools.getConnection();  
  181.             preparedStatement = connection.prepareStatement(sql);  
  182.   
  183.             for (int i = 0; i < args.length; i ) {  
  184.                 preparedStatement.setObject(i   1, args[i]);  
  185.             }  
  186.   
  187.             resultSet = preparedStatement.executeQuery();  
  188.               
  189.             if(resultSet.next()){  
  190.                 return (E) resultSet.getObject(1);  
  191.             }  
  192.         } catch(Exception ex){  
  193.             ex.printStackTrace();  
  194.         } finally{  
  195.             JDBCTools.releaseDB(resultSet, preparedStatement, connection);  
  196.         }  
  197.         //2. 取得结果  
  198.           
  199.         return null;  
  200.     }  
  201.   
  202. }  

 

5.事务和事务的隔离级别

 

 

[java] view plain copy

 

  1. package com.atguigu.jdbc;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.PreparedStatement;  
  5. import java.sql.ResultSet;  
  6. import java.sql.SQLException;  
  7.   
  8. import org.junit.Test;  
  9.   
  10. public class TransactionTest {  
  11.   
  12.     /** 
  13.      * 测试事务的隔离级别 在 JDBC 程序中可以通过 Connection 的 setTransactionIsolation 来设置事务的隔离级别. 
  14.      */  
  15.     @Test  
  16.     public void testTransactionIsolationUpdate() {  
  17.           
  18.         Connection connection = null;  
  19.   
  20.         try {  
  21.             connection = JDBCTools.getConnection();  
  22.             connection.setAutoCommit(false);  
  23.               
  24.             String sql = "UPDATE users SET balance = "  
  25.                       "balance - 500 WHERE id = 1";  
  26.             update(connection, sql);  
  27.               
  28.             connection.commit();  
  29.         } catch (Exception e) {  
  30.             e.printStackTrace();  
  31.         } finally {  
  32.   
  33.         }  
  34.     }  
  35.       
  36.     @Test  
  37.     public void testTransactionIsolationRead() {  
  38.         String sql = "SELECT balance FROM users WHERE id = 1";  
  39.         Integer balance = getForValue(sql);  
  40.         System.out.println(balance);   
  41.     }  
  42.   
  43.     // 返回某条记录的某一个字段的值 或 一个统计的值(一共有多少条记录等.)  
  44.     public <E> E getForValue(String sql, Object... args) {  
  45.   
  46.         // 1. 得到结果集: 该结果集应该只有一行, 且只有一列  
  47.         Connection connection = null;  
  48.         PreparedStatement preparedStatement = null;  
  49.         ResultSet resultSet = null;  
  50.   
  51.         try {  
  52.             // 1. 得到结果集  
  53.             connection = JDBCTools.getConnection();  
  54.             System.out.println(connection.getTransactionIsolation());   
  55.               
  56. //          connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);  
  57.             connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);  
  58.               
  59.             preparedStatement = connection.prepareStatement(sql);  
  60.   
  61.             for (int i = 0; i < args.length; i ) {  
  62.                 preparedStatement.setObject(i   1, args[i]);  
  63.             }  
  64.   
  65.             resultSet = preparedStatement.executeQuery();  
  66.   
  67.             if (resultSet.next()) {  
  68.                 return (E) resultSet.getObject(1);  
  69.             }  
  70.         } catch (Exception ex) {  
  71.             ex.printStackTrace();  
  72.         } finally {  
  73.             JDBCTools.releaseDB(resultSet, preparedStatement, connection);  
  74.         }  
  75.         // 2. 取得结果  
  76.   
  77.         return null;  
  78.     }  
  79.   
  80.     /** 
  81.      * Tom 给 Jerry 汇款 500 元. 
  82.      *  
  83.      * 关于事务: 1. 如果多个操作, 每个操作使用的是自己的单独的连接, 则无法保证事务. 2. 具体步骤: 1). 事务操作开始前, 开始事务: 
  84.      * 取消 Connection 的默认提交行为. connection.setAutoCommit(false); 2). 如果事务的操作都成功, 
  85.      * 则提交事务: connection.commit(); 3). 回滚事务: 若出现异常, 则在 catch 块中回滚事务: 
  86.      */  
  87.     @Test  
  88.     public void testTransaction() {  
  89.   
  90.         Connection connection = null;  
  91.   
  92.         try {  
  93.   
  94.             connection = JDBCTools.getConnection();  
  95.             System.out.println(connection.getAutoCommit());  
  96.   
  97.             // 开始事务: 取消默认提交.  
  98.             connection.setAutoCommit(false);  
  99.   
  100.             String sql = "UPDATE users SET balance = "  
  101.                       "balance - 500 WHERE id = 1";  
  102.             update(connection, sql);  
  103.   
  104.             int i = 10 / 0;  
  105.             System.out.println(i);  
  106.   
  107.             sql = "UPDATE users SET balance = "   "balance   500 WHERE id = 2";  
  108.             update(connection, sql);  
  109.   
  110.             // 提交事务  
  111.             connection.commit();  
  112.         } catch (Exception e) {  
  113.             e.printStackTrace();  
  114.   
  115.             // 回滚事务  
  116.             try {  
  117.                 connection.rollback();  
  118.             } catch (SQLException e1) {  
  119.                 e1.printStackTrace();  
  120.             }  
  121.         } finally {  
  122.             JDBCTools.releaseDB(null, null, connection);  
  123.         }  
  124.   
  125.         /* 
  126.          * try { 
  127.          *  
  128.          * //开始事务: 取消默认提交. connection.setAutoCommit(false); 
  129.          *  
  130.          * //... 
  131.          *  
  132.          * //提交事务 connection.commit(); } catch (Exception e) { //... 
  133.          *  
  134.          * //回滚事务 try { connection.rollback(); } catch (SQLException e1) { 
  135.          * e1.printStackTrace(); } } finally{ JDBCTools.releaseDB(null, null, 
  136.          * connection); } 
  137.          */  
  138.   
  139.         // DAO dao = new DAO();  
  140.         //  
  141.         // String sql = "UPDATE users SET balance = "    
  142.         // "balance - 500 WHERE id = 1";  
  143.         // dao.update(sql);  
  144.         //  
  145.         // int i = 10 / 0;  
  146.         // System.out.println(i);  
  147.         //  
  148.         // sql = "UPDATE users SET balance = "    
  149.         // "balance   500 WHERE id = 2";  
  150.         // dao.update(sql);  
  151.   
  152.     }  
  153.   
  154.     public void update(Connection connection, String sql, Object... args) {  
  155.         PreparedStatement preparedStatement = null;  
  156.   
  157.         try {  
  158.             preparedStatement = connection.prepareStatement(sql);  
  159.   
  160.             for (int i = 0; i < args.length; i ) {  
  161.                 preparedStatement.setObject(i   1, args[i]);  
  162.             }  
  163.   
  164.             preparedStatement.executeUpdate();  
  165.         } catch (Exception e) {  
  166.             e.printStackTrace();  
  167.         } finally {  
  168.             JDBCTools.releaseDB(null, preparedStatement, null);  
  169.         }  
  170.     }  
  171.   
  172. }  

6.批量处理sql语句

 

 

 

[java] view plain copy

 

  1. @Test  
  2. public void testBatch(){  
  3.     Connection connection = null;  
  4.     PreparedStatement preparedStatement = null;  
  5.     String sql = null;  
  6.       
  7.     try {  
  8.         connection = JDBCTools.getConnection();  
  9.         JDBCTools.beginTx(connection);  
  10.         sql = "INSERT INTO customers VALUES(?,?,?)";  
  11.         preparedStatement = connection.prepareStatement(sql);  
  12.         Date date = new Date(new java.util.Date().getTime());  
  13.           
  14.         long begin = System.currentTimeMillis();  
  15.         for(int i = 0; i < 100000; i ){  
  16.             preparedStatement.setInt(1, i   1);  
  17.             preparedStatement.setString(2, "name_"   i);  
  18.             preparedStatement.setDate(3, date);  
  19.               
  20.             //"积攒" SQL   
  21.             preparedStatement.addBatch();  
  22.               
  23.             //当 "积攒" 到一定程度, 就统一的执行一次. 并且清空先前 "积攒" 的 SQL  
  24.             if((i   1) % 300 == 0){  
  25.                 preparedStatement.executeBatch();  
  26.                 preparedStatement.clearBatch();  
  27.             }  
  28.         }  
  29.           
  30.         //若总条数不是批量数值的整数倍, 则还需要再额外的执行一次.   
  31.         if(100000 % 300 != 0){  
  32.             preparedStatement.executeBatch();  
  33.             preparedStatement.clearBatch();  
  34.         }  
  35.           
  36.         long end = System.currentTimeMillis();  
  37.           
  38.         System.out.println("Time: "   (end - begin)); //569  
  39.           
  40.         JDBCTools.commit(connection);  
  41.     } catch (Exception e) {  
  42.         e.printStackTrace();  
  43.         JDBCTools.rollback(connection);  
  44.     } finally{  
  45.         JDBCTools.releaseDB(null, preparedStatement, connection);  
  46.     }  
  47. }  

 

 

7.DBCP和C3P0数据库连接池的使用(非配置文件和配置文件)

 

 

 

[java] view plain copy

 

  1. package com.atguigu.jdbc;  
  2.   
  3. import java.beans.PropertyVetoException;  
  4. import java.io.InputStream;  
  5. import java.sql.Connection;  
  6. import java.sql.Date;  
  7. import java.sql.PreparedStatement;  
  8. import java.sql.SQLException;  
  9. import java.sql.Statement;  
  10. import java.util.Properties;  
  11.   
  12. import javax.sql.DataSource;  
  13.   
  14. import org.apache.commons.dbcp.BasicDataSource;  
  15. import org.apache.commons.dbcp.BasicDataSourceFactory;  
  16. import org.junit.Test;  
  17.   
  18. import com.mchange.v2.c3p0.ComboPooledDataSource;  
  19.   
  20. public class JDBCTest {  
  21.       
  22.     @Test  
  23.     public void testJdbcTools() throws Exception{  
  24.         Connection connection = JDBCTools.getConnection();  
  25.         System.out.println(connection);   
  26.     }  
  27.       
  28.     /** 
  29.      * 1. 创建 c3p0-config.xml 文件,  
  30.      * 参考帮助文档中 Appendix B: Configuation Files 的内容 
  31.      * 2. 创建 ComboPooledDataSource 实例; 
  32.      * DataSource dataSource =  
  33.      *          new ComboPooledDataSource("helloc3p0");   
  34.      * 3. 从 DataSource 实例中获取数据库连接.  
  35.      */  
  36.     @Test  
  37.     public void testC3poWithConfigFile() throws Exception{  
  38.         DataSource dataSource =   
  39.                 new ComboPooledDataSource("helloc3p0");    
  40.           
  41.         System.out.println(dataSource.getConnection());   
  42.           
  43.         ComboPooledDataSource comboPooledDataSource =   
  44. 澳门新萄京官方网站,                (ComboPooledDataSource) dataSource;  
  45.         System.out.println(comboPooledDataSource.getMaxStatements());   
  46.     }  
  47.       
  48.     @Test  
  49.     public void testC3P0() throws Exception{  
  50.         ComboPooledDataSource cpds = new ComboPooledDataSource();  
  51.         cpds.setDriverClass( "com.mysql.jdbc.Driver" ); //loads the jdbc driver              
  52.         cpds.setJdbcUrl( "jdbc:mysql:///atguigu" );  
  53.         cpds.setUser("root");                                    
  54.         cpds.setPassword("1230");     
  55.           
  56.         System.out.println(cpds.getConnection());   
  57.     }  
  58.       
  59.     /** 
  60.      * 1. 加载 dbcp 的 properties 配置文件: 配置文件中的键需要来自 BasicDataSource 
  61.      * 的属性. 
  62.      * 2. 调用 BasicDataSourceFactory 的 createDataSource 方法创建 DataSource 
  63.      * 实例 
  64.      * 3. 从 DataSource 实例中获取数据库连接.  
  65.      */  
  66.     @Test  
  67.     public void testDBCPWithDataSourceFactory() throws Exception{  
  68.           
  69.         Properties properties = new Properties();  
  70.         InputStream inStream = JDBCTest.class.getClassLoader()  
  71.                 .getResourceAsStream("dbcp.properties");  
  72.         properties.load(inStream);  
  73.           
  74.         DataSource dataSource =   
  75.                 BasicDataSourceFactory.createDataSource(properties);  
  76.           
  77.         System.out.println(dataSource.getConnection());   
  78.           
  79. //      BasicDataSource basicDataSource =   
  80. //              (BasicDataSource) dataSource;  
  81. //        
  82. //      System.out.println(basicDataSource.getMaxWait());   
  83.     }  
  84.       
  85.     /** 
  86.      * 使用 DBCP 数据库连接池 
  87.      * 1. 加入 jar 包(2 个jar 包). 依赖于 Commons Pool 
  88.      * 2. 创建数据库连接池 
  89. 行使连接池前后连接数据库的对峙统风流倜傥。     * 3. 为数据源实例指定必须的属性 
  90.      * 4. 从数据源中获取数据库连接 
  91.      * @throws SQLException  
  92.      */  
  93.     @Test  
  94.     public void testDBCP() throws SQLException{  
  95.         final BasicDataSource dataSource = new BasicDataSource();  
  96.           
  97.         //2. 为数据源实例指定必须的属性  
  98.         dataSource.setUsername("root");  
  99.         dataSource.setPassword("1230");  
  100.         dataSource.setUrl("jdbc:mysql:///atguigu");  
  101.         dataSource.setDriverClassName("com.mysql.jdbc.Driver");  
  102.           
  103.         //3. 指定数据源的一些可选的属性.  
  104.         //1). 指定数据库连接池中初始化连接数的个数  
  105.         dataSource.setInitialSize(5);  
  106.           
  107.         //2). 指定最大的连接数: 同一时刻可以同时向数据库申请的连接数  
  108.         dataSource.setMaxActive(5);  
  109.           
  110.         //3). 指定小连接数: 在数据库连接池中保存的最少的空闲连接的数量   
  111.         dataSource.setMinIdle(2);  
  112.           
  113.         //4).等待数据库连接池分配连接的最长时间. 单位为毫秒. 超出该时间将抛出异常.   
  114.         dataSource.setMaxWait(1000 * 5);  
  115.           
  116.         //4. 从数据源中获取数据库连接  
  117.         Connection connection = dataSource.getConnection();  
  118.         System.out.println(connection.getClass());   
  119.           
  120.         connection = dataSource.getConnection();  
  121.         System.out.println(connection.getClass());   
  122.           
  123.         connection = dataSource.getConnection();  
  124.         System.out.println(connection.getClass());   
  125.           
  126.         connection = dataSource.getConnection();  
  127.         System.out.println(connection.getClass());   
  128.           
  129.         Connection connection2 = dataSource.getConnection();  
  130.         System.out.println(">"   connection2.getClass());   
  131.           
  132.         new Thread(){  
  133.             public void run() {  
  134.                 Connection conn;  
  135.                 try {  
  136.                     conn = dataSource.getConnection();  
  137.                     System.out.println(conn.getClass());   
  138.                 } catch (SQLException e) {  
  139.                     e.printStackTrace();  
  140.                 }  
  141.             };  
  142.         }.start();  
  143.           
  144.         try {  
  145.             Thread.sleep(5500);  
  146.         } catch (InterruptedException e) {  
  147.             e.printStackTrace();  
  148.         }  
  149.           
  150.         connection2.close();  
  151.     }  
  152.       
  153.     @Test  
  154.     public void testBatch(){  
  155.         Connection connection = null;  
  156.         PreparedStatement preparedStatement = null;  
  157.         String sql = null;  
  158.           
  159.         try {  
  160.             connection = JDBCTools.getConnection();  
  161.             JDBCTools.beginTx(connection);  
  162.             sql = "INSERT INTO customers VALUES(?,?,?)";  
  163.             preparedStatement = connection.prepareStatement(sql);  
  164.             Date date = new Date(new java.util.Date().getTime());  
  165.               
  166.             long begin = System.currentTimeMillis();  
  167.             for(int i = 0; i < 100000; i ){  
  168.                 preparedStatement.setInt(1, i   1);  
  169.                 preparedStatement.setString(2, "name_"   i);  
  170.                 preparedStatement.setDate(3, date);  
  171.                   
  172.                 //"积攒" SQL   
  173.                 preparedStatement.addBatch();  
  174.                   
  175.                 //当 "积攒" 到一定程度, 就统一的执行一次. 并且清空先前 "积攒" 的 SQL  
  176.                 if((i   1) % 300 == 0){  
  177.                     preparedStatement.executeBatch();  
  178.                     preparedStatement.clearBatch();  
  179.                 }  
  180.             }  
  181.               
  182.             //若总条数不是批量数值的整数倍, 则还需要再额外的执行一次.   
  183.             if(100000 % 300 != 0){  
  184.                 preparedStatement.executeBatch();  
  185.                 preparedStatement.clearBatch();  
  186.             }  
  187.               
  188.             long end = System.currentTimeMillis();  
  189.               
  190.             System.out.println("Time: "   (end - begin)); //569  
  191.               
  192.             JDBCTools.commit(connection);  
  193.         } catch (Exception e) {  
  194.             e.printStackTrace();  
  195.             JDBCTools.rollback(connection);  
  196.         } finally{  
  197.             JDBCTools.releaseDB(null, preparedStatement, connection);  
  198.         }  
  199.     }  
  200.       
  201.   
  202.     @Test  
  203.     public void testBatchWithPreparedStatement(){  
  204.         Connection connection = null;  
  205.         PreparedStatement preparedStatement = null;  
  206.         String sql = null;  
  207.           
  208.         try {  
  209.             connection = JDBCTools.getConnection();  
  210.             JDBCTools.beginTx(connection);  
  211.             sql = "INSERT INTO customers VALUES(?,?,?)";  
  212.             preparedStatement = connection.prepareStatement(sql);  
  213.             Date date = new Date(new java.util.Date().getTime());  
  214.               
  215.             long begin = System.currentTimeMillis();  
  216.             for(int i = 0; i < 100000; i ){  
  217.                 preparedStatement.setInt(1, i   1);  
  218.                 preparedStatement.setString(2, "name_"   i);  
  219.                 preparedStatement.setDate(3, date);  
  220.                   
  221.                 preparedStatement.executeUpdate();  
  222.             }  
  223.             long end = System.currentTimeMillis();  
  224.               
  225.             System.out.println("Time: "   (end - begin)); //9819  
  226.               
  227.             JDBCTools.commit(connection);  
  228.         } catch (Exception e) {  
  229.             e.printStackTrace();  
  230.             JDBCTools.rollback(connection);  
  231.         } finally{  
  232.             JDBCTools.releaseDB(null, preparedStatement, connection);  
  233.         }  
  234.     }  
  235.       
  236.     /** 
  237.      * 向  Oracle 的 customers 数据表中插入 10 万条记录 
  238.      * 测试如何插入, 用时最短.  
  239.      * 1. 使用 Statement. 
  240.      */  
  241.     @Test  
  242.     public void testBatchWithStatement(){  
  243.         Connection connection = null;  
  244.         Statement statement = null;  
  245.         String sql = null;  
  246.           
  247.         try {  
  248.             connection = JDBCTools.getConnection();  
  249.             JDBCTools.beginTx(connection);  
  250.               
  251.             statement = connection.createStatement();  
  252.               
  253.             long begin = System.currentTimeMillis();  
  254.             for(int i = 0; i < 100000; i ){  
  255.                 sql = "INSERT INTO customers VALUES("   (i   1)   
  256.                           ", 'name_"   i   "', '29-6月 -13')";  
  257.                 statement.addBatch(sql);  
  258.             }  
  259.             long end = System.currentTimeMillis();  
  260.               
  261.             System.out.println("Time: "   (end - begin)); //39567  
  262.               
  263.             JDBCTools.commit(connection);  
  264.         } catch (Exception e) {  
  265.             e.printStackTrace();  
  266.             JDBCTools.rollback(connection);  
  267.         } finally{  
  268.             JDBCTools.releaseDB(null, statement, connection);  
  269.         }  
  270.     }  
  271.   
  272. }  

 

 

8.DBUtils使用

 

 

 

[java] view plain copy

 

  1. package com.atguigu.jdbc;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.Date;  
  5. import java.sql.ResultSet;  
  6. import java.sql.SQLException;  
  7. import java.util.ArrayList;  
  8. import java.util.List;  
  9. import java.util.Map;  
  10.   
  11. import org.apache.commons.dbutils.QueryRunner;  
  12. import org.apache.commons.dbutils.ResultSetHandler;  
  13. import org.apache.commons.dbutils.handlers.BeanHandler;  
  14. import org.apache.commons.dbutils.handlers.BeanListHandler;  
  15. import org.apache.commons.dbutils.handlers.MapHandler;  
  16. import org.apache.commons.dbutils.handlers.MapListHandler;  
  17. import org.apache.commons.dbutils.handlers.ScalarHandler;  
  18. import org.junit.Test;  
  19.   
  20. public class DBUtilsTest {  
  21.   
  22.       
  23.       
  24.     /** 
  25.      * ScalarHandler: 把结果集转为一个数值(可以是任意基本数据类型和字符串, Date 等)返回 
  26.      */  
  27.     @Test  
  28.     public void testScalarHandler(){  
  29.         Connection connection = null;  
  30.           
  31.         try {  
  32.             connection = JDBCTools.getConnection();  
  33.             String sql = "SELECT name, email "    
  34.                     "FROM customers";  
  35.               
  36.             Object result = queryRunner.query(connection,   
  37.                     sql, new ScalarHandler());  
  38.               
  39.             System.out.println(result);  
  40.         } catch (Exception e) {  
  41.             e.printStackTrace();  
  42.         } finally{  
  43.             JDBCTools.releaseDB(null, null, connection);  
  44.         }  
  45.     }  
  46.       
  47.     /** 
  48.      * MapListHandler: 将结果集转为一个 Map 的 List 
  49.      * Map 对应查询的一条记录: 键: SQL 查询的列名(不是列的别名), 值: 列的值.  
  50.      * 而 MapListHandler: 返回的多条记录对应的 Map 的集合.  
  51.      */  
  52.     @Test  
  53.     public void testMapListHandler(){  
  54.         Connection connection = null;  
  55.           
  56.         try {  
  57.             connection = JDBCTools.getConnection();  
  58.             String sql = "SELECT id, name, email, birth "    
  59.                     "FROM customers";  
  60.               
  61.             List<Map<String, Object>> result = queryRunner.query(connection,   
  62.                     sql, new MapListHandler());  
  63.               
  64.             System.out.println(result);  
  65.         } catch (Exception e) {  
  66.             e.printStackTrace();  
  67.         } finally{  
  68.             JDBCTools.releaseDB(null, null, connection);  
  69.         }  
  70.     }  
  71.       
  72.     /** 
  73.      * MapHandler: 返回 SQL 对应的第一条记录对应的 Map 对象. 
  74.      * 键: SQL 查询的列名(不是列的别名), 值: 列的值.  
  75.      */  
  76.     @Test  
  77.     public void testMapHandler(){  
  78.         Connection connection = null;  
  79.           
  80.         try {  
  81.             connection = JDBCTools.getConnection();  
  82.             String sql = "SELECT id, name, email, birth "    
  83.                     "FROM customers";  
  84.               
  85.             Map<String, Object> result = queryRunner.query(connection,   
  86.                     sql, new MapHandler());  
  87.               
  88.             System.out.println(result);  
  89.         } catch (Exception e) {  
  90.             e.printStackTrace();  
  91.         } finally{  
  92.             JDBCTools.releaseDB(null, null, connection);  
  93.         }  
  94.     }  
  95.       
  96.     /** 
  97.      * BeanListHandler: 把结果集转为一个 List, 该 List 不为 null, 但可能为 
  98.      * 空集合(size() 方法返回 0) 
  99.      * 若 SQL 语句的确能够查询到记录, List 中存放创建 BeanListHandler 传入的 Class 
  100.      * 对象对应的对象.  
  101.      */  
  102.     @Test  
  103.     public void testBeanListHandler(){  
  104.         Connection connection = null;  
  105.           
  106.         try {  
  107.             connection = JDBCTools.getConnection();  
  108.             String sql = "SELECT id, name, email, birth "    
  109.                     "FROM customers";  
  110.               
  111.             List<Customer> customers = queryRunner.query(connection,   
  112.                     sql, new BeanListHandler(Customer.class));  
  113.               
  114.             System.out.println(customers);  
  115.         } catch (Exception e) {  
  116.             e.printStackTrace();  
  117.         } finally{  
  118.             JDBCTools.releaseDB(null, null, connection);  
  119.         }  
  120.     }  
  121.       
  122.     /** 
  123.      * BeanHandler: 把结果集的第一条记录转为创建 BeanHandler 对象时传入的 Class 
  124.      * 参数对应的对象.  
  125.      */  
  126.     @Test  
  127.     public void testBeanHanlder(){  
  128.         Connection connection = null;  
  129.           
  130.         try {  
  131.             connection = JDBCTools.getConnection();  
  132.             String sql = "SELECT id, name customerName, email, birth "    
  133.                     "FROM customers WHERE id >= ?";  
  134.               
  135.             Customer customer = queryRunner.query(connection,   
  136.                     sql, new BeanHandler(Customer.class), 5);  
  137.               
  138.             System.out.println(customer);  
  139.         } catch (Exception e) {  
  140.             e.printStackTrace();  
  141.         } finally{  
  142.             JDBCTools.releaseDB(null, null, connection);  
  143.         }  
  144.     }  
  145.       
  146.     QueryRunner queryRunner = new QueryRunner();  
  147.   
  148.     class MyResultSetHandler implements ResultSetHandler{  
  149.   
  150.         @Override  
  151.         public Object handle(ResultSet resultSet)   
  152.                 throws SQLException {  
  153. //          System.out.println("handle....");  
  154. //          return "atguigu";  
  155.               
  156.             List<Customer> customers = new ArrayList<>();  
  157.               
  158.             while(resultSet.next()){  
  159.                 Integer id = resultSet.getInt(1);  
  160.                 String name = resultSet.getString(2);  
  161.                 String email = resultSet.getString(3);  
  162.                 Date birth = resultSet.getDate(4);  
  163.                   
  164.                 Customer customer =   
  165.                         new Customer(id, name, email, birth);  
  166.                 customers.add(customer);  
  167.             }  
  168.               
  169.             return customers;  
  170.         }  
  171.           
  172.     }  
  173.       
  174.     /** 
  175.      * QueryRunner 的 query 方法的返回值取决于其 ResultSetHandler 参数的 
  176.      * handle 方法的返回值 
  177.      *  
  178.      */  
  179.     @Test  
  180.     public void testQuery(){  
  181.         Connection connection = null;  
  182.           
  183.         try {  
  184.             connection = JDBCTools.getConnection();  
  185.             String sql = "SELECT id, name, email, birth "    
  186.                     "FROM customers";  
  187.             Object obj = queryRunner.query(connection, sql,   
  188.                             new MyResultSetHandler());  
  189.               
  190.             System.out.println(obj);   
  191.         } catch (Exception e) {  
  192.             e.printStackTrace();  
  193.         } finally{  
  194.             JDBCTools.releaseDB(null, null, connection);  
  195.         }  
  196.     }  
  197.       
  198.     @Test  
  199.     public void testUpdate(){  
  200.         Connection connection = null;  
  201.           
  202.         try {  
  203.             connection = JDBCTools.getConnection();  
  204.             String sql = "UPDATE customers SET name = ? "    
  205.                     "WHERE id = ?";  
  206.             queryRunner.update(connection, sql, "MIKE", 11);  
  207.         } catch (Exception e) {  
  208.             e.printStackTrace();  
  209.         } finally{  
  210.             JDBCTools.releaseDB(null, null, connection);  
  211.         }  
  212.     }  
  213.   
  214. }  

 

9.DAO接口

 

 

 

[java] view plain copy

 

  1. package com.atguigu.jdbc;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.SQLException;  
  5. import java.util.List;  
  6.   
  7. /** 
  8.  * 访问数据的 DAO 接口.  
  9.  * 里边定义好访问数据表的各种方法 
  10.  * @param T: DAO 处理的实体类的类型.  
  11.  */  
  12. public interface DAO<T> {  
  13.   
  14.     /** 
  15.      * 批量处理的方法 
  16.      * @param connection 
  17.      * @param sql 
  18.      * @param args: 填充占位符的 Object [] 类型的可变参数. 
  19.      * @throws SQLException  
  20.      */    
  21.     void batch(Connection connection,   
  22.             String sql, Object [] ... args) throws SQLException;  
  23.       
  24.     /** 
  25.      * 返回具体的一个值, 例如总人数, 平均工资, 某一个人的 email 等. 
  26.      * @param connection 
  27.      * @param sql 
  28.      * @param args 
  29.      * @return 
  30.      * @throws SQLException  
  31.      */  
  32.     <E> E getForValue(Connection connection,  
  33.             String sql, Object ... args) throws SQLException;  
  34.       
  35.     /** 
  36.      * 返回 T 的一个集合 
  37.      * @param connection 
  38.      * @param sql 
  39.      * @param args 
  40.      * @return 
  41.      * @throws SQLException  
  42.      */  
  43.     List<T> getForList(Connection connection,  
  44.             String sql, Object ... args) throws SQLException;  
  45.       
  46.     /** 
  47.      * 返回一个 T 的对象 
  48.      * @param connection 
  49.      * @param sql 
  50.      * @param args 
  51.      * @return 
  52.      * @throws SQLException  
  53.      */  
  54.     T get(Connection connection, String sql,   
  55.             Object ... args) throws SQLException;  
  56.       
  57.     /** 
  58.      * INSRET, UPDATE, DELETE 
  59.      * @param connection: 数据库连接 
  60.      * @param sql: SQL 语句 
  61.      * @param args: 填充占位符的可变参数. 
  62.      * @throws SQLException  
  63.      */  
  64.     void update(Connection connection, String sql,   
  65.             Object ... args) throws SQLException;  
  66.   
  67. }  

10.DAO接口的实现类。(通过DBUtils实现)

 

 

 

 

[java] view plain copy

 

  1. package com.atguigu.jdbc;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.SQLException;  
  5. import java.util.List;  
  6.   
  7. import org.apache.commons.dbutils.QueryRunner;  
  8. import org.apache.commons.dbutils.handlers.BeanHandler;  
  9. import org.apache.commons.dbutils.handlers.BeanListHandler;  
  10. import org.apache.commons.dbutils.handlers.ScalarHandler;  
  11.   
  12. /** 
  13.  * 使用 QueryRunner 提供其具体的实现 
  14.  * @param <T>: 子类需传入的泛型类型.  
  15.  */  
  16. public class JdbcDaoImpl<T> implements DAO<T> {  
  17.   
  18.     private QueryRunner queryRunner = null;  
  19.     private Class<T> type;  
  20.       
  21.     public JdbcDaoImpl() {  
  22.         queryRunner = new QueryRunner();  
  23.         type = ReflectionUtils.getSuperGenericType(getClass());  
  24.     }  
  25.       
  26.     @Override  
  27.     public void batch(Connection connection, String sql, Object[]... args) throws SQLException {  
  28.         queryRunner.batch(connection, sql, args);  
  29.     }  
  30.   
  31.     @Override  
  32.     public <E> E getForValue(Connection connection, String sql, Object... args) throws SQLException {  
  33.         return (E) queryRunner.query(connection, sql, new ScalarHandler(), args);  
  34.     }  
  35.   
  36.     @Override   
  37.     public List<T> getForList(Connection connection, String sql, Object... args)   
  38.             throws SQLException {  
  39.         return queryRunner.query(connection, sql,   
  40.                 new BeanListHandler<>(type), args);  
  41.     }  
  42.   
  43.     @Override  
  44.     public T get(Connection connection, String sql, Object... args) throws SQLException {   
  45.         return queryRunner.query(connection, sql,   
  46.                 new BeanHandler<>(type), args);  
  47.     }  
  48.   
  49.     @Override  
  50.     public void update(Connection connection, String sql, Object... args) throws SQLException {  
  51.         queryRunner.update(connection, sql, args);  
  52.     }  
  53.       
  54. }  

 

 

11.DAOImpl的继承类,可以再自己定义操作数据库的方法

 

 

 

[java] view plain copy

 

  1. package com.atguigu.jdbc;  
  2.   
  3. public class CustomerDao   
  4.     extends JdbcDaoImpl<Customer>{  
  5.       
  6. }  

然后,为什么使用连接池?

1.1.1 需求:

网上商城中对分类添加,修改,删除,查询的操作.使用JDBC完成对分类的CRUD的操作.

          我们不仅仅要求连接到数据库,更需要连接的效率。这就需要连接池了。也就是说,我提前连接好n个连接,需要的时候,我在池里取就行,不用再现创现用了,速度快了,效            率高了。连接池有c3p0,dbcp等,有文章专门介绍过几种连接池的区别。结论就是c3p0是使用最广泛的。

1.1.2 分析:

下面比较使用连接池前后的效率

1.1.2.1 技术分析

【JDBC的回顾】

  • JDBC的概念:

JDBC:Java Data Base Connectivity.

  • 驱动:

 

  • JDBC的开发步骤:

步骤一:注册驱动.

步骤二:获得连接.
步骤三:创建执行SQL语句对象.

步骤四:释放资源.

  • JDBC的API的详解:

DriverManager:

    * 注册驱动:

    * 获得连接:

Connection:

    * 获得执行SQL语句对象.

        * Statement createStatement();

        * PreparedStatement prepareStatement(String sql);

        * CallableStatement prepareCall(String sql);

    * 进行事务管理:

        * setAutoCommit(boolean flag);

        * commit();

        * rollback();

Statement:

    * 执行SQL语句:

        * int executeUpate(String sql); --执行insert update delete语句.

        * ResultSet executeQuery(String sql); --执行select语句.

        * boolean execute(String sql); --执行select返回true 执行其他的语句返回false.

  

ResultSet:

    * 遍历结果集:next();

    * 获得结果集中的数据.getXXX(int c); getXXX(String name);

1 建一个pool管理类 Mpool

1.1.2.2 步骤分析

  • 步骤一:创建Java项目,引入mysql的驱动包.
  • 步骤二:编写程序
  • 步骤三:注册驱动
  • 步骤四:获得连接
  • 步骤五:执行SQL
  • 步骤六:释放资源

package com.db;

1.1.3 代码实现:

抽取工具类:

package com.itheima.jdbc.utils;

 

import java.io.FileInputStream;

import java.io.FileNotFoundException;

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;

 

/**

 * JDBC的工具类

 * @author apple

 *

 */

public class JDBCUtils {

public static final String DRIVERCLASS;

public static final String URL;

public static final String USERNAME;

public static final String PASSWORD;

 

static{

// 获得属性文件中的数据.

Properties properties = new Properties();

try {

properties.load(new FileInputStream("src/db.properties"));

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

 

DRIVERCLASS = properties.getProperty("jdbc.driverClass");

URL = properties.getProperty("jdbc.url");

USERNAME = properties.getProperty("jdbc.username");

PASSWORD = properties.getProperty("jdbc.password");

}

 

// 加载驱动:

public static void loadDriver(){

try {

Class.forName(DRIVERCLASS);

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

// 获得连接:

public static Connection getConnection(){

loadDriver();

Connection conn = null;

try {

conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return conn;

}

 

// 释放资源:

public static void release(Statement stmt,Connection conn){

if(stmt != null){

try {

stmt.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

stmt = null;

}

 

if(conn != null){

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

conn = null;

}

}

 

public static void release(ResultSet rs,Statement stmt,Connection conn){

if(rs!= null){

try {

rs.close();

} catch (SQLException e) {

e.printStackTrace();

}

rs = null;

}

if(stmt != null){

try {

stmt.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

stmt = null;

}

 

if(conn != null){

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

conn = null;

}

}

}

 

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

1.2 使用连接池改造JDBC的程序:

import com.mchange.v2.c3p0.ComboPooledDataSource;

1.2.1 需求:

提升程序运行的效率,采用连接池对JDBC的部分的效率进行提升.

public class Mpool {
private static Mpool mPool;
private ComboPooledDataSource dataSource;

1.2.2 分析:

static {
mPool = new Mpool();
}
//构造方法
public Mpool() {
try {
dataSource = new ComboPooledDataSource("mysql");
dataSource.setUser("root");
dataSource.setPassword("root123");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test02");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setInitialPoolSize(2);
dataSource.setMinPoolSize(1);
dataSource.setMaxPoolSize(10);
dataSource.setMaxStatements(50);
dataSource.setMaxIdleTime(60);
} catch (PropertyVetoException e) {
throw new RuntimeException(e);
}
}

1.2.2.1 技术分析:

【连接池的概述】

  • 为什么使用连接池

Connection对象在JDBC使用的时候.使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了.每次创建和销毁对象都是耗时操作.需要使用连接池对其进行优化.程序初始化的时候,初始化多个连接,将多个连接放入到池中(内存中).每次获取的时候,都可以直接从连接池中进行获取.使用结束以后,将连接归还到池中.

  • 常见连接池:

DBCP :Apache.

C3P0 :

【连接池的原理】

在javax.sql.DataSource接口--连接池的接口

* 功能:初始化多个连接.把多个连接放入到内存中.

* 归还:将连接对象放回到内存中.

【自定义连接池--了解】

public class MyDataSource implements DataSource{

 

// 创建一个集合List集合.

List<Connection> list = new ArrayList<Connection>();

 

// 初始化连接池的时候,初始化5个连接.

public  MyDataSource() {

for (int i = 1; i <= 5; i ) {

Connection conn = JDBCUtils.getConnection();

list.add(conn);

}

}

 

@Override

// 从连接池中获得连接

public Connection getConnection() throws SQLException {

if(list.size()==0){

for (int i = 1; i <= 3; i ) {

Connection conn = JDBCUtils.getConnection();

list.add(conn);

}

}

Connection conn = list.remove(0);

return conn;

}

 

// 归还连接:

public void addBack(Connection conn){

list.add(conn);

}

...

}

 

【自定义连接池中问题】

1.创建连接池的时候能不能面向接口编程.

2.额外增加连接池的方法,那么程序员需要记住这些方法.能不能不额外去提供一些方法.

***** 解决:就是要去增强Connection的close方法.

       1.继承的方法:

            * 继承的使用条件:能够控制这个类的构造.

       2.装饰者模式:(*****)

            * 装饰者模式的使用条件:

                * 2.1增强的类和被增强的类实现相同的接口.

                * 2.2在增强的类中能够获得被增强的类的引用.

            * 接口中方法过多,只增强其中的一个方法.其他方法都需要原样调用原有方法.

       3.动态代理:(*****)

            * JDK的动态代理使用条件:

                 * 被代理的对象必须实现接口.

【使用开源连接池优化程序】

  • DBCP连接池:

 

核心API:

 

 

@Test

/**

 * DBCP的一个入门:手动设置参数

 */

public void demo1(){

Connection conn = null;

PreparedStatement pstmt = null;

 

// 创建连接池:

BasicDataSource dataSource = new BasicDataSource();

dataSource.setDriverClassName("com.mysql.jdbc.Driver");

dataSource.setUrl("jdbc:mysql:///web07");

dataSource.setUsername("root");

dataSource.setPassword("1234");

try{

// 获得连接:

conn = dataSource.getConnection();

// 编写SQL语句.

String sql = "insert into category values (null,?)";

// 预编译SQL:

pstmt = conn.prepareStatement(sql);

// 设置参数:

pstmt.setString(1, "鞋靴箱包");

//执行SQL

pstmt.executeUpdate();

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(pstmt, conn);

}

}

 

@Test

/**

 * DBCP的带有配置文件的方式

 */

public void demo2(){

Connection conn = null;

PreparedStatement pstmt = null;

 

// 创建连接池:

try{

Properties properties = new Properties();

properties.load(new FileInputStream("src/dbcp.properties"));

DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);

// 获得连接:

conn = dataSource.getConnection();

// 编写SQL语句.

String sql = "insert into category values (null,?)";

// 预编译SQL:

pstmt = conn.prepareStatement(sql);

// 设置参数:

pstmt.setString(1, "生活用品");

//执行SQL

pstmt.executeUpdate();

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(pstmt, conn);

}

}

 

DBCP的参数的设置:

#连接设置

driverClassName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/jdbc

username=root

password=1234

 

#<!-- 初始化连接 -->

initialSize=10

 

#最大连接数量

maxActive=50

 

#<!-- 最大空闲连接 -->

maxIdle=20

 

#<!-- 最小空闲连接 -->

minIdle=5

 

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->

maxWait=60000

  • C3P0连接池的使用:

 

 

代码实现:

@Test

/**

 * 手动设置参数的方式:

 */

public void demo1(){

Connection conn = null;

PreparedStatement stmt = null;

// System.err.println("");

try{

// 创建连接池:

ComboPooledDataSource dataSource = new ComboPooledDataSource();

// 设置参数:

dataSource.setDriverClass("com.mysql.jdbc.Driver");

dataSource.setJdbcUrl("jdbc:mysql:///web07");

dataSource.setUser("root");

dataSource.setPassword("1234");

 

conn = dataSource.getConnection();

// 编写SQL

String sql = "insert into category values (null,?)";

// 预编译SQL:

stmt = conn.prepareStatement(sql);

// 设置参数:

stmt.setString(1, "食品饮料");

stmt.executeUpdate();

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(stmt, conn);

}

}

 

@Test

/**

 * 配置文件的方式:

 */

public void demo2(){

Connection conn = null;

PreparedStatement stmt = null;

// System.err.println("");

try{

// 创建连接池:

ComboPooledDataSource dataSource = new ComboPooledDataSource("mysql11111");

 

conn = dataSource.getConnection();

// 编写SQL

String sql = "insert into category values (null,?)";

// 预编译SQL:

stmt = conn.prepareStatement(sql);

// 设置参数:

stmt.setString(1, "食品饮料222");

stmt.executeUpdate();

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(stmt, conn);

}

}

【使用C3P0改写了工具类】

public class JDBCUtils2 {

 

private static final ComboPooledDataSource DATASOURCE =new ComboPooledDataSource();

 

public Connection getConnection(){

Connection conn = null;

try {

conn = DATASOURCE.getConnection();

} catch (SQLException e) {

e.printStackTrace();

}

return conn;

}

     ...

}

public final static Mpool getInstance() {
return mPool;
}

1.3 DBUtils完成CRUD的操作

public final Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException("无法从数据源获取连接 ", e);
}
}

1.3.1 需求:

简化DAO的开发.

}

1.3.2 分析:

2 测试类 main

1.3.2.1 技术分析:

DBUtils

【概述】

DBUtils是java编程中的数据库操作实用工具,小巧简单实用。

DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。

Dbutils三个核心功能介绍

l QueryRunner中提供对sql语句操作的API.

l ResultSetHandler接口,用于定义select操作后,怎样封装结果集.

l DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法

 

【QueryRunner核心类】

l QueryRunner(DataSource ds) ,提供数据源(连接池),DBUtils底层自动维护连接connection

l update(String sql, Object... params) ,执行更新数据

l query(String sql, ResultSetHandler<T> rsh, Object... params) ,执行查询

 

【ResultSetHandler结果集处理类】

ArrayHandler

将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值

ArrayListHandler

将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。

BeanHandler

将结果集中第一条记录封装到一个指定的javaBean中。

BeanListHandler

将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中

ColumnListHandler

将结果集中指定的列的字段值,封装到一个List集合中

KeyedHandler

将结果集中每一条记录封装到Map<String,Object>,在将这个map集合做为另一个Map的value,另一个Map集合的key是指定的字段的值。

MapHandler

将结果集中第一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值

 

MapListHandler

将结果集中每一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值,在将这些Map封装到List集合中。

ScalarHandler

它是用于单数据。例如select count(*) from 表操作。

 

【DbUtils】

closeQuietly(Connection conn) 关闭连接,如果有异常try后不抛。

commitAndCloseQuietly(Connection conn) 提交并关闭连接

rollbackAndCloseQuietly(Connection conn) 回滚并关闭连接

 

import java.sql.*;
import com.db.Mpool;;

public class Test {

public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("使用连接池.......................");
for (int i = 0; i < 20; i ) {
long beginTime = System.currentTimeMillis();

//1 获取一个连接
Connection conn = Mpool.getInstance().getConnection();
try {

//2 这个连接要干嘛,封装在PreparedStatement准备对象中.不可以采用拼接的形式了,采用占位符。
/* PreparedStatement pstmt = conn
.prepareStatement("insert into user(userName,password) value(" i ",111)");
*/
PreparedStatement pstmt = conn
.prepareStatement("insert into user(userName,password) values(?,?)");
pstmt.setInt(1, i);
pstmt.setInt(2, i);
//3 准备好以后,执行准备对象

/* 3-1执行查询对象 ResultSet rs = pstmt.executeQuery();*/

//3-2 执行插入 更新等的准备对象
//Boolean a= pstmt.execute(); //如果第第一个结果是结果集 返回true。
//建议使用executeUpadate() 执行结果可以看到,0表示没有执行
int a= pstmt.executeUpdate();
System.out.println(a);

/* 如果是查询语句,则re存在返回结果。
while (rs.next()) {
re.get内容

}*/
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
long endTime = System.currentTimeMillis();
System.out.println("第" (i 1) "次执行花费时间为:"

  • (endTime - beginTime));
    }

}

}

 

 

3 只是用jdbc测试

import java.sql.*;

public class Test1 {

public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("不使用连接池................................");
for (int i = 0; i < 20; i ) {
long beginTime = System.currentTimeMillis();
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
} catch (Exception e1) {
e1.printStackTrace();
}
String url = "jdbc:mysql://localhost:3306/test02";
String user = "root";
String password = "root123";
Connection conn=null;
try {
//直接使用jdbc获取conn
conn = DriverManager.getConnection(url, user, password);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
PreparedStatement pstmt = conn
.prepareStatement("insert into user(userName,password) values(?,?)");
pstmt.setInt(1, i);
pstmt.setInt(2, i);

int a =pstmt.executeUpdate();
System.out.println(a);
/* while (rs.next()) {
// get content
}*/
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
long endTime = System.currentTimeMillis();
System.out.println("第" (i 1) "次执行花费时间为:"

  • (endTime - beginTime));
    }
    }
    }

 可以发现: 使用jdbc直接连接数据库,每次连接需要的时间都差不多,40秒左右。而使用连接池的话,第一次连接需要的时间比较长,因为要做一些初始化操作吧,第二次获取连接的时间大概是1秒,很快的。

另外注意,对数据库的操作也是有影响的,比如查询和写入操作,时间就不一样。

 

本文由澳门新萄京官方网站发布于数据库网络,转载请注明出处:行使连接池前后连接数据库的对峙统风流倜傥

关键词: