JDBC数据源连接池的配置和使用实例

个人学习参考所用,勿喷!

 

使用JDBC建立数据库连接的两种方式:

1.在代码中使用DriverManager获得数据库连接。这种方式效率低,并且其性能、可靠性和稳定性随着用户访问量得增加逐渐下降。

2.使用配置数据源的方式连接数据库,该方式其实质就是在上述方法的基础上增加了数据库连接池,这种方式效率高。

 

数据源连接池的方式连接数据库与在代码中使用DriverManager获得数据库连接存在如下差别:

1) 数据源连接池的方式连接数据库是在程序中,通过向一个JNDI(Java Naming and  Directory Interface)服务器查询,即调用Context接口的lookup()方法,来得到DataSource对象,然后调用DataSource对象 的getConnection()方法建立连接

2) 为了能重复利用数据库连接对象,提高对请求的响应时间和服务器的性能,采用连接池技术.连接池技术预先建立多个数据库连接对象,然后将连接对象保存到连接 池中,当客户请求到来时,从池中取出一个连接对象为客户服务,当请求完成时,客户程序调用close()方法,将连接对象放回池中.

3) 在代码中使用DriverManager获得数据库连接的方式中,客户程序得到的连接对象是物理连接,调用连接对象的close()方法将关闭连接,而采 用连接池技术,客户程序得到的连接对象是连接池中物理连接的一个句柄,调用连接对象的close()方法,物理连接并没有关闭,数据源的实现只是删除了客 户程序中的连接对象和池中的连接对象之间的联系.

 

为了测试方便可以在数据库(这里以mysql 5为例)中建立一个USER表:

Sql代码  JDBC数据源连接池的配置和使用实例
  1. <span style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: x-small;">CREATE TABLE `user` (  
  2.   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  
  3.   `username` varchar(50) DEFAULT NULL,  
  4.   `password` varchar(50) DEFAULT NULL,  
  5.   `email` varchar(50) DEFAULT NULL,  
  6.   PRIMARY KEY (`id`),  
  7. );</span>  

 

导入数据库的驱动的jar包到tomcat的lib目录下(这里以mysql5为例,所用到的jar包为:mysql-connector-java-5.0.8-bin.jar)。

 

1.在代码中使用DriverManager获得数据库连接。这种方式效率低,并且其性能、可靠性和稳定性随着用户访问量得增加逐渐下降。

   oracle数据库连接的Java代码如下:

Java代码  JDBC数据源连接池的配置和使用实例
  1. import java.sql.Connection;  
  2. import java.sql.DriverManager;  
  3. /** 
  4.  * 获取数据库连接 
  5.  */  
  6. public class DBConnection {  
  7.       
  8.     /** Oracle数据库连接URL*/  
  9.     private final static String DB_URL = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";  
  10.       
  11.     /** Oracle数据库连接驱动*/  
  12.     private final static String DB_DRIVER = "oracle.jdbc.driver.OracleDriver";  
  13.       
  14.     /** 数据库用户名*/  
  15.     private final static String DB_USERNAME = "root";  
  16.       
  17.     /** 数据库密码*/  
  18.     private final static String DB_PASSWORD = "admin";  
  19.       
  20.     /** 
  21.      * 获取数据库连接 
  22.      * @return 
  23.      */  
  24.     public Connection getConnection(){  
  25.         /** 声明Connection连接对象*/  
  26.         Connection conn = null;  
  27.         try{  
  28.             /** 使用Class.forName()方法自动创建这个驱动程序的实例且自动调用DriverManager来注册它*/  
  29.             Class.forName(DB_DRIVER);  
  30.             /** 通过DriverManager的getConnection()方法获取数据库连接*/  
  31.             conn = DriverManager.getConnection(DB_URL,DB_USERNAME,DB_PASSWORD);  
  32.         }catch(Exception ex){  
  33.             ex.printStackTrace();  
  34.         }  
  35.         return conn;  
  36.     }  
  37.       
  38.     /** 
  39.      * 关闭数据库连接 
  40.      *  
  41.      * @param connect 
  42.      */  
  43.     public void closeConnection(Connection conn){  
  44.         try{  
  45.             if(conn!=null){  
  46.                 /** 判断当前连接连接对象如果没有被关闭就调用关闭方法*/  
  47.                 if(!conn.isClosed()){  
  48.                     conn.close();  
  49.                 }  
  50.             }  
  51.         }catch(Exception ex){  
  52.             ex.printStackTrace();  
  53.         }  
  54.     }  
  55.       
  56. }  

 

 mysql数据库连接的JSP代码如下:

Jsp代码  JDBC数据源连接池的配置和使用实例
  1. <%@page import="java.sql.*, com.mysql.jdbc.Driver"%>  
  2. <%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>  
  3. <html>  
  4. <body>      
  5.     <%  
  6.     //com.mysql.jdbc.Driver  
  7.     Class.forName(Driver.class.getName()).newInstance();  
  8.     String url = "jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF8";  
  9.     String user = "root";  
  10.     String password = "123";  
  11.       
  12.     Connection conn = DriverManager.getConnection(url, user, password);  
  13.     Statement stmt = conn.createStatement();  
  14.       
  15.     String sql = "select * from user";  
  16.     ResultSet rs = stmt.executeQuery(sql);  
  17.       
  18.     while(rs.next()) {  
  19.         out.print("<br />" + "====================" + "<br />");  
  20.         out.print(rs.getLong("id") + "   ");  
  21.         out.print(rs.getString("username") + "   ");  
  22.         out.print(rs.getString("password") + "   ");  
  23.         out.print(rs.getString("email") + "   ");  
  24.     }  
  25.     %>  
  26. </body>  
  27. </html>  

 

2.使用配置数据源的方式连接数据库,该方式其实质就是在上述方法的基础上增加了数据库连接池,这种方式效率高。

1)mysql数据库数据源连接池的JSP代码如下:

Jsp代码  JDBC数据源连接池的配置和使用实例
  1. <%@page import="java.sql.*, javax.naming.*, javax.sql.DataSource"%>  
  2. <%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>  
  3. <html>  
  4. <body>  
  5.     <%  
  6.     Context initCtx = new InitialContext();  
  7.     DataSource ds = (DataSource)initCtx.lookup("java:comp/env/jdbc/demoDB");  
  8.     Connection conn = ds.getConnection();  
  9.       
  10.     Statement stmt = conn.createStatement();  
  11.       
  12.     String sql = "select * from user";  
  13.     ResultSet rs = stmt.executeQuery(sql);  
  14.       
  15.     while(rs.next()) {  
  16.         out.print("<br />" + "====================" + "<br />");  
  17.         out.print(rs.getLong("id") + "   ");  
  18.         out.print(rs.getString("username") + "   ");  
  19.         out.print(rs.getString("password") + "   ");  
  20.         out.print(rs.getString("email") + "   ");  
  21.     }  
  22.     %>  
  23. </body>  
  24. </html>  

 

2) 添加如下代码到tomcat的conf目录下的server.xml中:

Xml代码  JDBC数据源连接池的配置和使用实例
  1. <Context>   
  2.     <Resource name="jdbc/demoDB" auth="Container"   
  3.     type="javax.sql.DataSource"  
  4.     driverClassName="com.mysql.jdbc.Driver"  
  5.     url="jdbc:mysql://localhost:3306/demo"  
  6.     username="root"  
  7.     password="123"  
  8.     maxActive="50"  
  9.     maxIdle="30"  
  10.     maxWait="10000" />  
  11. </Context>  

 

3)在web工程目录下的web.xml的根节点下配置如下内容:

Xml代码  JDBC数据源连接池的配置和使用实例
  1. <resource-ref>  
  2.     <description>mysqlDB Connection</description>  
  3.     <res-ref-name>jdbc/demoDB</res-ref-name>  
  4.     <res-type>javax.sql.DataSource</res-type>  
  5.     <res-auth>Container</res-auth>  
  6. </resource-ref>  

 

 完成上述步骤数据源的连接池配置已经完成,但是为了提高项目的可移植性,最好将上述第二步的内容放入到工程的META-INF目录的context.xml中(这个文件需要自行建立):

Xml代码  JDBC数据源连接池的配置和使用实例
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <Context>  
  3.       <Resource name="jdbc/demoDB" auth="Container"   
  4.       type="javax.sql.DataSource"  
  5.       driverClassName="com.mysql.jdbc.Driver"  
  6.       url="jdbc:mysql://localhost:3306/demo"  
  7.       username="root"  
  8.       password="123"  
  9.       maxActive="50"  
  10.       maxIdle="30"  
  11.       maxWait="10000" />  
  12. </Context>  

 

3.使用配置数据源的数据库连接池时的数据库操作工具类

代码如下:

Java代码  JDBC数据源连接池的配置和使用实例
  1. package db.utils;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.PreparedStatement;  
  5. import java.sql.ResultSet;  
  6. import java.sql.ResultSetMetaData;  
  7. import java.sql.SQLException;  
  8. import java.sql.Statement;  
  9. import java.text.DateFormat;  
  10. import java.util.ArrayList;  
  11. import java.util.Date;  
  12. import java.util.HashMap;  
  13. import java.util.List;  
  14. import java.util.Map;  
  15.   
  16. import javax.naming.InitialContext;  
  17. import javax.sql.DataSource;  
  18.   
  19. //import org.apache.log4j.Logger;  
  20.   
  21. /** 
  22.  * 数据库操作辅助类 
  23.  */  
  24. public class DbUtils {  
  25.       
  26.     //private static Logger logger = Logger.getLogger("DbUtils");  
  27.       
  28.     /** 
  29.      * 该语句必须是一个 SQL INSERT、UPDATE 或 DELETE 语句 
  30.      * @param sql 
  31.      * @param paramList:参数,与SQL语句中的占位符一一对应 
  32.      * @return 
  33.      * @throws Exception 
  34.      */  
  35.     public int execute(String sql, List<Object> paramList) throws Exception {  
  36.         if(sql == null || sql.trim().equals("")) {  
  37.             //logger.info("parameter is valid!");  
  38.         }  
  39.   
  40.         Connection conn = null;  
  41.         PreparedStatement pstmt = null;  
  42.         int result = 0;  
  43.         try {  
  44.             conn = getConnection();  
  45.             pstmt = DbUtils.getPreparedStatement(conn, sql);  
  46.             setPreparedStatementParam(pstmt, paramList);  
  47.             if(pstmt == null) {  
  48.                 return -1;  
  49.             }  
  50.             result = pstmt.executeUpdate();  
  51.         } catch (Exception e) {  
  52.             //logger.info(e.getMessage());  
  53.             throw new Exception(e);  
  54.         } finally {  
  55.             closeStatement(pstmt);  
  56.             closeConn(conn);  
  57.         }  
  58.   
  59.         return result;  
  60.     }  
  61.       
  62.     /** 
  63.      * 将查询数据库获得的结果集转换为Map对象 
  64.      * @param sql:查询语句 
  65.      * @param paramList:参数 
  66.      * @return 
  67.      */  
  68.     public List<Map<String, Object>> getQueryList(String sql, List<Object> paramList) throws Exception {  
  69.         if(sql == null || sql.trim().equals("")) {  
  70.             //logger.info("parameter is valid!");  
  71.             return null;  
  72.         }  
  73.   
  74.         Connection conn = null;  
  75.         PreparedStatement pstmt = null;  
  76.         ResultSet rs = null;  
  77.         List<Map<String, Object>> queryList = null;  
  78.         try {  
  79.             conn = getConnection();  
  80.             pstmt = DbUtils.getPreparedStatement(conn, sql);  
  81.             setPreparedStatementParam(pstmt, paramList);  
  82.             if(pstmt == null) {  
  83.                 return null;  
  84.             }  
  85.             rs = getResultSet(pstmt);  
  86.             queryList = getQueryList(rs);  
  87.         } catch (RuntimeException e) {  
  88.             //logger.info(e.getMessage());  
  89.             System.out.println("parameter is valid!");  
  90.             throw new Exception(e);  
  91.         } finally {  
  92.             closeResultSet(rs);  
  93.             closeStatement(pstmt);  
  94.             closeConn(conn);  
  95.         }  
  96.         return queryList;  
  97.     }  
  98.       
  99.     private void setPreparedStatementParam(PreparedStatement pstmt, List<Object> paramList) throws Exception {  
  100.         if(pstmt == null || paramList == null || paramList.isEmpty()) {  
  101.             return;  
  102.         }  
  103.         DateFormat df = DateFormat.getDateTimeInstance();  
  104.         for (int i = 0; i < paramList.size(); i++) {  
  105.             if(paramList.get(i) instanceof Integer) {  
  106.                 int paramValue = ((Integer)paramList.get(i)).intValue();  
  107.                 pstmt.setInt(i+1, paramValue);  
  108.             } else if(paramList.get(i) instanceof Float) {  
  109.                 float paramValue = ((Float)paramList.get(i)).floatValue();  
  110.                 pstmt.setFloat(i+1, paramValue);  
  111.             } else if(paramList.get(i) instanceof Double) {  
  112.                 double paramValue = ((Double)paramList.get(i)).doubleValue();  
  113.                 pstmt.setDouble(i+1, paramValue);  
  114.             } else if(paramList.get(i) instanceof Date) {  
  115.                 pstmt.setString(i+1, df.format((Date)paramList.get(i)));  
  116.             } else if(paramList.get(i) instanceof Long) {  
  117.                 long paramValue = ((Long)paramList.get(i)).longValue();  
  118.                 pstmt.setLong(i+1, paramValue);  
  119.             } else if(paramList.get(i) instanceof String) {  
  120.                 pstmt.setString(i+1, (String)paramList.get(i));  
  121.             }  
  122.         }  
  123.         return;  
  124.     }  
  125.       
  126.     /** 
  127.      * 获得数据库连接 
  128.      * @return 
  129.      * @throws Exception 
  130.      */  
  131.     private Connection getConnection() throws Exception {  
  132.         InitialContext cxt = new InitialContext();  
  133.         DataSource ds = (DataSource) cxt.lookup(jndiName);  
  134.         if ( ds == null ) {  
  135.            throw new Exception("Data source not found!");  
  136.         }  
  137.           
  138.         return ds.getConnection();  
  139.     }  
  140.       
  141.     private static PreparedStatement getPreparedStatement(Connection conn, String sql) throws Exception {  
  142.         if(conn == null || sql == null || sql.trim().equals("")) {  
  143.             return null;  
  144.         }  
  145.         PreparedStatement pstmt = conn.prepareStatement(sql.trim());  
  146.         return pstmt;  
  147.     }  
  148.       
  149.     /** 
  150.      * 获得数据库查询结果集 
  151.      * @param pstmt 
  152.      * @return 
  153.      * @throws Exception 
  154.      */  
  155.     private ResultSet getResultSet(PreparedStatement pstmt) throws Exception {  
  156.         if(pstmt == null) {  
  157.             return null;  
  158.         }  
  159.         ResultSet rs = pstmt.executeQuery();  
  160.         return rs;  
  161.     }  
  162.       
  163.     /** 
  164.      * @param rs 
  165.      * @return 
  166.      * @throws Exception 
  167.      */  
  168.     private List<Map<String, Object>> getQueryList(ResultSet rs) throws Exception {  
  169.         if(rs == null) {  
  170.             return null;  
  171.         }  
  172.         ResultSetMetaData rsMetaData = rs.getMetaData();  
  173.         int columnCount = rsMetaData.getColumnCount();  
  174.         List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();  
  175.         while (rs.next()) {  
  176.             Map<String, Object> dataMap = new HashMap<String, Object>();  
  177.             for (int i = 0; i < columnCount; i++) {  
  178.                 dataMap.put(rsMetaData.getColumnName(i+1), rs.getObject(i+1));  
  179.             }  
  180.             dataList.add(dataMap);  
  181.         }  
  182.         return dataList;  
  183.     }  
  184.       
  185.     /** 
  186.      * 关闭数据库连接 
  187.      * @param conn 
  188.      */  
  189.     private void closeConn(Connection conn) {  
  190.         if(conn == null) {  
  191.             return;  
  192.         }  
  193.         try {  
  194.             conn.close();  
  195.         } catch (SQLException e) {  
  196.             //logger.info(e.getMessage());  
  197.         }  
  198.     }  
  199.       
  200.     /** 
  201.      * 关闭 
  202.      * @param stmt 
  203.      */  
  204.     private void closeStatement(Statement stmt) {  
  205.         if(stmt == null) {  
  206.             return;  
  207.         }  
  208.         try {  
  209.             stmt.close();  
  210.         } catch (SQLException e) {  
  211.             //logger.info(e.getMessage());  
  212.         }  
  213.     }  
  214.       
  215.     /** 
  216.      * 关闭 
  217.      * @param rs 
  218.      */  
  219.     private void closeResultSet(ResultSet rs) {  
  220.         if(rs == null) {  
  221.             return;  
  222.         }  
  223.         try {  
  224.             rs.close();  
  225.         } catch (SQLException e) {  
  226.             //logger.info(e.getMessage());  
  227.         }  
  228.     }  
  229.       
  230.       
  231.     private String jndiName = "java:/comp/env/jdbc/demoDB";  
  232.   
  233.     public void setJndiName(String jndiName) {  
  234.         this.jndiName = jndiName;  
  235.     }  

 

原文:http://kingxss.iteye.com/blog/1479451

上一篇:Java数据库连接池的几种配置方法(以MySQL数据库为例)


下一篇:13. 存储过程与存储函数