转摘请注明出处
作者:baggio
来源:
本文地址;
关键词DataSource(数据源)Tomcat连接池
前言
本文根据实例详细介绍了如何在tomcat中配置数据源网上此类文章很多但是基本都是雷同的而且对一些特殊问题以及原理并未详细阐述所以想根据自己的实际经验并结合例子写一篇详细的文章
本文是偶的一些拙见有不正确的地方请大家多多评论指正
开发环境
本文的环境JDKTOMCATOraclei
JDBC简介
提到数据源那就不能不说JDBCJDBC是Java Database Connectivity的缩写在javasql包中提供了JDBC API定义了访问数据库的接口和类但是JDBC API不能直接访问数据库必须依赖于数据库厂商提供的JDBC驱动程序即JDBC DRIVER
Javasql中常用的接口和类如下
Driver接口和DriverManager类
Connection
Statement
PreparedSataement
ResultSet
Driver接口和DriverManager类
DriverManager类用来建立和数据库的连接以及管理JDBC驱动程序常用方法如下
方法 描述 registerDriver(Driver driver) 在DriverManager中注册JDBC驱动程序 getConnection(String urlString userString pwd) 建立和数据库的连接返回Connection对象 setLoginTimeOut(int seconds) 设定等待数据库连接的最长时间 setLogWriter(PrintWriter out) 设定输入数据库日至的PrintWriter对象
Connection
Connection代表和数据库的连接其常用方法如下
方法 描述 getMetaData() 返回数据库的MetaData数据MetaData数据包含了数据库的相关信息例如当前数据库连接的用户名使用的JDBC驱动程序数据库允许的最大连接数数据库的版本等等 createStatement() 创建并返回Statement对象 PrepareStatement(String sql) 创建并返回prepareStatement对象
Statement
Statement用来执行静态sql语句例如对于insertupdatedelete语句调用executeUpdate(String sql)方法而select语句可以调用executeQuery(String sql)方法executeQuery(String sql)方法返回ResultSet对象
PrepareStatement
PrepareStatement用于执行动态的sql语句即允许sql语句中包含参数使用方法为
String sql = select col from tablename where col=? And col=?;
PrepareStatement perpStmt = connpreparestatement(sql);
perpStmtsetstring(colValue);
perpStmtsetFloat(colValue);
ResultSet rs = perpStmtexecuteQuery();
ResultSet
ResultSet用来表示select语句查询得到的记录集一个StateMent对象在同一时刻只能打开一个ResultSet对象通过ResultSet的getXXX()方法来得到字段值ResultSet提供了getString()getFloat()getInt()等方法可以通过字段的序号或者字段的名字来制定获取某个字段的值例如在上例中getString()getString(col)都可以获得字段col的值
事务处理
在实际应用中我们会遇到同时提交多个sql语句这些sql语句要么全部成功要么全部失败如果其中一条提交失败则必须撤销整个事务为此Connection类提供了个控制事务的方法
方法 描述 setAutoCommit(boolen autoCommit) 设置是否自动提交事务默认为自动提交 commit() 提交事务 rollback() 撤销事务
参考例子
try{
connSetautoCommit(false);
stmt = conncreatestatement();
stmtexecuteUpdate(delete form table where col=);
stmteecuteUpdate(delete from table where col=);
();
}catch(Exception e){
eprintStackTrace;
try{
connrollback();
} catch(Exception e){
eprintStackTrace;
}
}
通过一个JSP例子来访问oracle数据库
<%@ page import=
java
util
*
>
<%@ page import=javasql*>
<%
try{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
//加载oracle驱动程序
ClassforName(oraclejdbcdriverOracleDriver);
//注册oracle驱动程序
DriverManagerregidterDriver(new
oraclejdbcdriverOracleDriver());
//建立数据库连接
conn=DriverManagergetConnection(jdbc:oracle:thin:@your
db ip:your db port:siddbuserdbpassword);
stmt = conncreateStatement();
rs = stmtexecuteQuery(select * from
tablename);
while(rsnext){
outprint(rsgetstring(colname));
}
}catch(Exception e){
}
finally{
rsclose();
stmtclose();
connclose();
}
%>
数据源简介
JDBC提供了javaxsqlDataSource的接口负责与数据库建立连接实际应用时不需要编写连接数据库代码直接从数据源获得数据库的连接Dataource中事先建立了多个数据库连接这些数据库连接保持在数据库连接池中当程序访问数据库时只需要从连接池从取出空闲的连接访问数据库结束在将这些连接归还给连接池DataSource对象由容器(Tomcat)提供不能使用创建实例的方法来生成DataSource对象要采用JAVA的JNDI(Java Nameing and Directory Interfacejava命名和目录接口)来获得DataSource对象的引用(另有一种说法其实从技术上来说数据源连接方式是不需要目录服务的我们同样可以通过序列化数据源对象直接访问文件系统这点是需要明确的感兴趣的朋友可以试试)JNDI是一种将对象和名字绑定的技术对象工厂负责生产出对象这些对象都和唯一的名字相绑定程序中可以通过这个名字来获得对象的引用Tomcat把DataSource作为一种可配置的JNDI资源来处理生成DataSource对象的工厂为monsdbcpBasicDataSourceFactory
配置数据源
配置数据源其实相当简单
首先在serverxml中加入<Resource>元素打开serverxml在<Context>中加入以下代码(以oracle为例)
<Resource name=jdbc/ JNDI名字 auth=Container type=javaxsqlDataSource/>
<ResourceParams name=jdbc/JNDI名字>
<parameter>
<name>factory</name>
<value>monsdbcpBasicDataSourceFactory</value>
</parameter>
<parameter>
<name>maxActive</name>
<value></value>
</parameter>
<parameter>
<name>maxIdle</name>
<value></value>
</parameter>
<parameter>
<name>maxWait</name>
<value></value>
</parameter>
<parameter>
<name>username</name>
<value>用户名</value>
</parameter>
<parameter>
<name>password</name>
<value>密码</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>oraclejdbcdriverOracleDriver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:oracle:thin:@ip:端口:sid </value>
</parameter>
</ResourceParams>
<Resource>元素的属性如下
属性 描述 name 指定Resource的JNDI的名字 auth 指定管理Resource的Manager
由两个可选值
Container和Application
Container表示由容器来创建和管理Resource
Application表示由WEB应用来创建和管理Resource
如果在web application deployment descriptor中使用<resource
ref>
这个属性是必需的
如果使用<resource
env
ref>
这个属性是可选的
type 指定Resource所属的java类名
<ResourceParams>元素的属性如下
属性 描述 name 指定ResourceParams的JNDI的名字必须和Resource的name保持一致 factory 指定生成DataSource对象的factory的类名 maxActive 指定数据库连接池中处于活动状态的数据库连接最大数目表示不受限制 maxIdle 指定数据库连接池中处于空闲状态的数据库连接的最大数目表示不受限制 maxWait 指定数据库连接池中的数据库连接处于空闲状态的最长时间(单位为毫秒)超过这一事件将会抛出异常表示可以无限期等待 username 指定连接数据库的用户名 password 指定连接数据库的密码 driverClassName 指定连接数据库的JDBC驱动程序 url 指定连接数据库的URL
其他文章说以上配置就OK了对于webxml的配置可有可无其实不是这样子的如果在web应用中访问了由Servlet容器管理的某个JNDI Resource则必须在webxml中声明对这个JNDI Resource的引用表示资源引用的元素为<resourceref>该元素加在<wepapp></ wepapp >中
<resourceref>
<descryiption>DB Connection</descryiption>
<resrefname>jdbc/JNDI名字 </resrefname>
<restype>javaxsqlDataSource </res type>
<resauth>Container </resauth>
</resourceref>
<resourceref>元素的属性如下
属性 描述 description 对所引用的资源的说明 resrefname 指定所引用资源的JNDI名字与<Resource>元素中的name属性保持一致 restype 指定所引用资源的类名字与<Resource>元素中的type属性保持一致 resauth 指定所引用资源的Manager与<Resource>元素中的auth属性保持一致
到这里数据源就已经配置成功了但是我在测试的时候除了一点小麻烦主要原因是对DataSource的概念没搞清楚我是这么测试的写一个测试类然后在eclipse中进行junit测试捕获的异常为
javaxnamingNoInitialContextException: Need to specify class name in environment or system property or as an applet parameter or in an application resource file:javanamingfactoryinitial
同样的代码在JSP文件中正常运行后来翻了一些资料终于找到了问题的所在了原来DataSource是由容器(TOMCAT)提供的所以我的测试会抛出异常为了再次验证想法是否正确在jsp文件中import刚才抛出异常的类在进行连接数据库结果一切正常
下面的例子是实际应用中使用DataSource在jsp文件中连接oracle
<%@ page language=java import=javautil* pageEncoding=UTF%>
<%@ page import=javasql*%>
<%@ page import=javaxnaming*%>
<%@ page import=javaxsql*%>
<!DOCTYPE HTML PUBLIC //WC//DTD
HTML Transitional//EN>
<html>
<head>
</head>
<body>
<%
Context initContext = new InitialContext();
Context envContext = (Context) initContextlookup(java:/comp/env);
DataSource db = (DataSource)envContextlookup(jdbc/javablogorl);
//javablogorl为<Resource>元素中name属性的值
Connection conn = dbgetConnection( );
Statement stmt = conncreateStatement();
ResultSet rs = stmtexecuteQuery(SELECT * FROM blog_systemadmin);
while(rsnext()){
outprint(rsgetString(admin_name)+ );
outprint(rsgetString(admin_password)+<br>);
}
rsclose();
stmtclose();
connclose();
%>
</body>
</html>
另:tomcat的配制方法为:
<Resourcename=jdbc/JNDI名字auth=Containertype=javaxsqlDataSource
maxActive=maxIdle=maxWait=
username=用户名password=密码driverClassName=oraclejdbcdriverOracleDriver
url=jdbc:oracle:thin:@ip:端口:sid/>