JDBC数据源连接池配置及应用
使用JDBC建立数据库连接的两种方式:
1.在代码中使用DriverManager获得数据库连接。这种方式效率低,并且其性能、可靠性和稳定性随着用户访问量得增加逐渐下降。
2.使用配置数据源的方式连接数据库,该方式其实质就是在上述方法的基础上增加了数据库连接池,这种方式效率高。
数据源连接池的方式连接数据库与在代码中使用DriverManager获得数据库连接存在如下差别:
1)数据源连接池的方式连接数据库是在程序中,通过向一个JNDI(JavaNamingand DirectoryInterface)服务器查询,即调用Context接口的lookup()方法,来得到DataSource对象,然后调用DataSource对象的getConnection()方法建立连接
2)为了能重复利用数据库连接对象,提高对请求的响应时间和服务器的性能,采用连接池技术.连接池技术预先建立多个数据库连接对象,然后将连接对象保存到连接池中,当客户请求到来时,从池中取出一个连接对象为客户服务,当请求完成时,客户程序调用close()方法,将连接对象放回池中.
3)在代码中使用DriverManager获得数据库连接的方式中,客户程序得到的连接对象是物理连接,调用连接对象的close()方法将关闭连接,而采用连接池技术,客户程序得到的连接对象是连接池中物理连接的一个句柄,调用连接对象的close()方法,物理连接并没有关闭,数据源的实现只是删除了客户程序中的连接对象和池中的连接对象之间的联系.
为了测试方便可以在数据库(这里以mysql5为例)中建立一个USER表:
CREATETABLE`user`( `id`int(10)unsignedNOTNULLAUTO_INCREMENT, `username`varchar(50)DEFAULTNULL, `password`varchar(50)DEFAULTNULL, `email`varchar(50)DEFAULTNULL, PRIMARYKEY(`id`), );
导入数据库的驱动的jar包到tomcat的lib目录下(这里以mysql5为例,所用到的jar包为:mysql-connector-java-5.0.8-bin.jar)。
1.在代码中使用DriverManager获得数据库连接。这种方式效率低,并且其性能、可靠性和稳定性随着用户访问量得增加逐渐下降。
oracle数据库连接的Java代码如下:
importjava.sql.Connection; importjava.sql.DriverManager; /** *获取数据库连接 */ publicclassDBConnection{ /**Oracle数据库连接URL*/ privatefinalstaticStringDB_URL="jdbc:oracle:thin:@127.0.0.1:1521:orcl"; /**Oracle数据库连接驱动*/ privatefinalstaticStringDB_DRIVER="oracle.jdbc.driver.OracleDriver"; /**数据库用户名*/ privatefinalstaticStringDB_USERNAME="root"; /**数据库密码*/ privatefinalstaticStringDB_PASSWORD="admin"; /** *获取数据库连接 *@return */ publicConnectiongetConnection(){ /**声明Connection连接对象*/ Connectionconn=null; try{ /**使用Class.forName()方法自动创建这个驱动程序的实例且自动调用DriverManager来注册它*/ Class.forName(DB_DRIVER); /**通过DriverManager的getConnection()方法获取数据库连接*/ conn=DriverManager.getConnection(DB_URL,DB_USERNAME,DB_PASSWORD); }catch(Exceptionex){ ex.printStackTrace(); } returnconn; } /** *关闭数据库连接 * *@paramconnect */ publicvoidcloseConnection(Connectionconn){ try{ if(conn!=null){ /**判断当前连接连接对象如果没有被关闭就调用关闭方法*/ if(!conn.isClosed()){ conn.close(); } } }catch(Exceptionex){ ex.printStackTrace(); } } }
mysql数据库连接的JSP代码如下:
<%@pageimport="java.sql.*,com.mysql.jdbc.Driver"%> <%@pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%> <html> <body> <% //com.mysql.jdbc.Driver Class.forName(Driver.class.getName()).newInstance(); Stringurl="jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF8"; Stringuser="root"; Stringpassword="123"; Connectionconn=DriverManager.getConnection(url,user,password); Statementstmt=conn.createStatement(); Stringsql="select*fromuser"; ResultSetrs=stmt.executeQuery(sql); while(rs.next()){ out.print("<br/>"+"===================="+"<br/>"); out.print(rs.getLong("id")+""); out.print(rs.getString("username")+""); out.print(rs.getString("password")+""); out.print(rs.getString("email")+""); } %> </body> </html>
2.使用配置数据源的方式连接数据库,该方式其实质就是在上述方法的基础上增加了数据库连接池,这种方式效率高。
1)mysql数据库数据源连接池的JSP代码如下:
<%@pageimport="java.sql.*,javax.naming.*,javax.sql.DataSource"%> <%@pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%> <html> <body> <% ContextinitCtx=newInitialContext(); DataSourceds=(DataSource)initCtx.lookup("java:comp/env/jdbc/demoDB"); Connectionconn=ds.getConnection(); Statementstmt=conn.createStatement(); Stringsql="select*fromuser"; ResultSetrs=stmt.executeQuery(sql); while(rs.next()){ out.print("<br/>"+"===================="+"<br/>"); out.print(rs.getLong("id")+""); out.print(rs.getString("username")+""); out.print(rs.getString("password")+""); out.print(rs.getString("email")+""); } %> </body> </html>
2)添加如下代码到tomcat的conf目录下的server.xml中:
<Context> <Resourcename="jdbc/demoDB"auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/demo" username="root" password="123" maxActive="50" maxIdle="30" maxWait="10000"/> </Context>
3)在web工程目录下的web.xml的根节点下配置如下内容:
<resource-ref> <description>mysqlDBConnection</description> <res-ref-name>jdbc/demoDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
完成上述步骤数据源的连接池配置已经完成,但是为了提高项目的可移植性,最好将上述第二步的内容放入到工程的META-INF目录的context.xml中(这个文件需要自行建立):
<?xmlversion="1.0"encoding="UTF-8"?> <Context> <Resourcename="jdbc/demoDB"auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/demo" username="root" password="123" maxActive="50" maxIdle="30" maxWait="10000"/> </Context>
3.使用配置数据源的数据库连接池时的数据库操作工具类
代码如下:
packagedb.utils; importjava.sql.Connection; importjava.sql.PreparedStatement; importjava.sql.ResultSet; importjava.sql.ResultSetMetaData; importjava.sql.SQLException; importjava.sql.Statement; importjava.text.DateFormat; importjava.util.ArrayList; importjava.util.Date; importjava.util.HashMap; importjava.util.List; importjava.util.Map; importjavax.naming.InitialContext; importjavax.sql.DataSource; //importorg.apache.log4j.Logger; /** *数据库操作辅助类 */ publicclassDbUtils{ //privatestaticLoggerlogger=Logger.getLogger("DbUtils"); /** *该语句必须是一个SQLINSERT、UPDATE或DELETE语句 *@paramsql *@paramparamList:参数,与SQL语句中的占位符一一对应 *@return *@throwsException */ publicintexecute(Stringsql,List<Object>paramList)throwsException{ if(sql==null||sql.trim().equals("")){ //logger.info("parameterisvalid!"); } Connectionconn=null; PreparedStatementpstmt=null; intresult=0; try{ conn=getConnection(); pstmt=DbUtils.getPreparedStatement(conn,sql); setPreparedStatementParam(pstmt,paramList); if(pstmt==null){ return-1; } result=pstmt.executeUpdate(); }catch(Exceptione){ //logger.info(e.getMessage()); thrownewException(e); }finally{ closeStatement(pstmt); closeConn(conn); } returnresult; } /** *将查询数据库获得的结果集转换为Map对象 *@paramsql:查询语句 *@paramparamList:参数 *@return */ publicList<Map<String,Object>>getQueryList(Stringsql,List<Object>paramList)throwsException{ if(sql==null||sql.trim().equals("")){ //logger.info("parameterisvalid!"); returnnull; } Connectionconn=null; PreparedStatementpstmt=null; ResultSetrs=null; List<Map<String,Object>>queryList=null; try{ conn=getConnection(); pstmt=DbUtils.getPreparedStatement(conn,sql); setPreparedStatementParam(pstmt,paramList); if(pstmt==null){ returnnull; } rs=getResultSet(pstmt); queryList=getQueryList(rs); }catch(RuntimeExceptione){ //logger.info(e.getMessage()); System.out.println("parameterisvalid!"); thrownewException(e); }finally{ closeResultSet(rs); closeStatement(pstmt); closeConn(conn); } returnqueryList; } privatevoidsetPreparedStatementParam(PreparedStatementpstmt,List<Object>paramList)throwsException{ if(pstmt==null||paramList==null||paramList.isEmpty()){ return; } DateFormatdf=DateFormat.getDateTimeInstance(); for(inti=0;i<paramList.size();i++){ if(paramList.get(i)instanceofInteger){ intparamValue=((Integer)paramList.get(i)).intValue(); pstmt.setInt(i+1,paramValue); }elseif(paramList.get(i)instanceofFloat){ floatparamValue=((Float)paramList.get(i)).floatValue(); pstmt.setFloat(i+1,paramValue); }elseif(paramList.get(i)instanceofDouble){ doubleparamValue=((Double)paramList.get(i)).doubleValue(); pstmt.setDouble(i+1,paramValue); }elseif(paramList.get(i)instanceofDate){ pstmt.setString(i+1,df.format((Date)paramList.get(i))); }elseif(paramList.get(i)instanceofLong){ longparamValue=((Long)paramList.get(i)).longValue(); pstmt.setLong(i+1,paramValue); }elseif(paramList.get(i)instanceofString){ pstmt.setString(i+1,(String)paramList.get(i)); } } return; } /** *获得数据库连接 *@return *@throwsException */ privateConnectiongetConnection()throwsException{ InitialContextcxt=newInitialContext(); DataSourceds=(DataSource)cxt.lookup(jndiName); if(ds==null){ thrownewException("Datasourcenotfound!"); } returnds.getConnection(); } privatestaticPreparedStatementgetPreparedStatement(Connectionconn,Stringsql)throwsException{ if(conn==null||sql==null||sql.trim().equals("")){ returnnull; } PreparedStatementpstmt=conn.prepareStatement(sql.trim()); returnpstmt; } /** *获得数据库查询结果集 *@parampstmt *@return *@throwsException */ privateResultSetgetResultSet(PreparedStatementpstmt)throwsException{ if(pstmt==null){ returnnull; } ResultSetrs=pstmt.executeQuery(); returnrs; } /** *@paramrs *@return *@throwsException */ privateList<Map<String,Object>>getQueryList(ResultSetrs)throwsException{ if(rs==null){ returnnull; } ResultSetMetaDatarsMetaData=rs.getMetaData(); intcolumnCount=rsMetaData.getColumnCount(); List<Map<String,Object>>dataList=newArrayList<Map<String,Object>>(); while(rs.next()){ Map<String,Object>dataMap=newHashMap<String,Object>(); for(inti=0;i<columnCount;i++){ dataMap.put(rsMetaData.getColumnName(i+1),rs.getObject(i+1)); } dataList.add(dataMap); } returndataList; } /** *关闭数据库连接 *@paramconn */ privatevoidcloseConn(Connectionconn){ if(conn==null){ return; } try{ conn.close(); }catch(SQLExceptione){ //logger.info(e.getMessage()); } } /** *关闭 *@paramstmt */ privatevoidcloseStatement(Statementstmt){ if(stmt==null){ return; } try{ stmt.close(); }catch(SQLExceptione){ //logger.info(e.getMessage()); } } /** *关闭 *@paramrs */ privatevoidcloseResultSet(ResultSetrs){ if(rs==null){ return; } try{ rs.close(); }catch(SQLExceptione){ //logger.info(e.getMessage()); } } privateStringjndiName="java:/comp/env/jdbc/demoDB"; publicvoidsetJndiName(StringjndiName){ this.jndiName=jndiName; } }
总结:使用配置数据源的方式连接数据库,这种方式效率高且性能稳定,推荐使用。
查看更多Java的语法,大家可以关注:《ThinkinginJava中文手册》、《JDK1.7参考手册官方英文版》、《JDK1.6APIjava中文参考手册》、《JDK1.5APIjava中文参考手册》,也希望大家多多支持毛票票。