什么是JDBC?
Java语言访问数据库的一种规范,是一套API
JDBC (Java Database Connectivity) API,即Java数据库编程接口,是一组标准的Java语言中的接口和类,使用这些接口和类,Java客户端程序可以访问各种不同类型的数据库。比如建立数据库连接、执行SQL语句进行数据的存取操作。
JDBC规范采用接口和实现分离的思想设计了Java数据库编程的框架。接口包含在java.sql及javax.sql包中,其中java.sql属于JavaSE,javax.sql属于JavaEE。这些接口的实现类叫做数据库驱动程序,由数据库的厂商或其它的厂商或个人提供。
为了使客户端程序独立于特定的数据库驱动程序,JDBC规范建议开发者使用基于接口的编程方式,即尽量使应用仅依赖java.sql及javax.sql中的接口和类。
JDBC驱动程序:
什么是JDBC驱动程序?
这些是各个数据库厂家根据JDBC的规范制作的JDBC实现类
JDBC驱动程序的四种类型:
1. 第一种类型的驱动程序的实现是通过将JDBC的调用全部委托给其它编程接口来实现的,比如ODBC。这种类型的驱动程序需要安装本地代码库,即依赖于本地的程序,所以便携性较差。比如JDBC-ODBC桥驱动程序
2. 第二种类型的驱动程序的实现是部分基于Java语言的。即该驱动程序一部分是用Java语言编写,其它部分委托本地的数据库的客户端代码来实现。同类型1的驱动一样,该类型的驱动程序也依赖本地的程序,所以便携性较差
3. 第三种类型的驱动程序的实现是全部基于JAVA语言的。该类型的驱动程序通常由某个中间件服务器提供,这样客户端程序可以使用数据库无关的协议和中间件服务器进行通信,中间件服务器再将客户端的JDBC调用转发给数据库进行处理
4. 第四种类型的驱动程序的实现是全部基于JAVA语言的。该类型的驱动程序中包含了特定数据库的访问协议,使得客户端可以直接和数据库进行通信
JDBC类结构:
DriverManager
Driver Driver
Connection Connection
Statement Statement
Resultset Resultset
DriverManager:这个是一个实现类,它是一个工厂类,用来生产Driver对象的
这个类的结构设计模式为工厂方法
Driver:这是驱动程序对象的接口,它指向一个实实在在的数据库驱动程序对象,那么这个数据库驱动程序对象是从哪里来的呢?
DriverManager工厂中有个方法:getDriver(String URL),通过这个方法可以得到驱动程序对象,这个方法是在各个数据库厂商按JDBC规范设计的数据库驱动程序包里的类中静态实现的,也就是在静态块中
Connection:这个接口可以制向一个数据库连接对象,那么如何得到这个连接对象呢?
是通过DriverManager工厂中的getConnection(String URL)方法得到的
Statement:用于执行静态的SQL语句的接口,通过Connection中的createStatement方法得到的
Resultset:用于指向结果集对象的接口,结果集对象是通过Statement中的execute等方法得到的
JAVA使用JDBC访问数据库的步骤:
1. 得到数据库驱动程序
2. 创建数据库连接
3. 执行SQL语句
4. 得到结果集
5. 对结果集做相应的处理(增,删,改,查)
6. 关闭资源:这里释放的是DB中的资源
设置classpath:
1. 在java文件中起的包名一定要是工程基目录下的子目录,classpath:基目录
2. .jar包,需要将这个.jar包的路径包括这个文件的全名添加到classpath中来
Oracle连接字符串的书写格式:
“oracle:jdbc:thin:@ip:1521: 数据库名”,”数据库用户名”,”数据库密码”
简单的例子:
package moudule1.first;
import java.sql.*;
public class FirstJdbc
{
public static void main(String[] args)
{
String sql="select * from yuchen_user";
Connection con=null;
Statement st=null;
ResultSet rs=null;
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:name", "scott","tiger");
st=con.createStatement();
rs=st.executeQuery(sql);
while(rs.next())
{
System.out.println(rs.getInt("id"));
System.out.println(rs.getString("name"));
}
}catch(Exception e)
{
e.printStackTrace();
}finally
{
try
{
con.close();
}catch(Exception e)
{}
try
{
st.close();
}catch(Exception e)
{
}
try
{
rs.close();
}catch(Exception e)
{
}
}
}
}
常用数据库的驱动程序及JDBC URL:
Oracle数据库:
驱动程序包名:ojdbc14.jar
驱动类的名字:oracle.jdbc.driver.OracleDriver
JDBC URL:jdbc:oracle:thin:@dbip:port:databasename
说明:驱动程序包名有可能会变
JDBC URL中黑色字体部分必须原封不动的保留,为该驱动识别的URL格式。红色字体部分需要根据数据库的安装情况填写。其中各个部分含义如下:
dbip –为数据库服务器的IP地址,如果是本地可写:localhost或127.0.0.1。
port –为数据库的监听端口,需要看安装时的配置,缺省为1521。
databasename –为数据库的SID,通常为全局数据库的名字。
举例如果要访问本地的数据库allandb,端口1521,那么URL写法如下:
jdbc:oracle:thin:@localhost:1521:allandb 下载地址如下:
http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/index.html
SQL Server数据库
驱动程序包名:msbase.jar mssqlserver.jar msutil.jar
驱动类的名字:com.microsoft.jdbc.sqlserver.SQLServerDriver
JDBC URL:jdbc:microsoft:sqlserver://dbip:port;DatabaseName=databasename
说明:驱动程序包名有可能会变
JDBC URL中黑色字体部分必须原封不动的保留,为该驱动识别的URL格式。红色字体部需要根据数据库的安装情况填写。其中各个部分含义如下:
dbip –为数据库服务器的IP地址,如果是本地可写:localhost或127.0.0.1。
port –为数据库的监听端口,需要看安装时的配置,缺省为1433。
databasename –数据库的名字。
举例如果要访问本地的数据库allandb,端口1433,那么URL写法如下:
jdbc: microsoft: sqlserver:@localhost:1433; DatabaseName =allandb
下载地址:http://www.microsoft.com/downloads/details.aspx
MySQL数据库
驱动程序包名:mysql-connector-java-3.1.11-bin.jar
驱动类的名字:com.mysql.jdbc.Driver
JDBC URL:jdbc:mysql://dbip:port/databasename
说明:驱动程序包名有可能会变
JDBC URL中黑色字体部分必须原封不动的保留,为该驱动识别的URL格式。红色字体部需要根据数据库的安装情况填写。其中各个部分含义如下:
dbip –为数据库服务器的IP地址,如果是本地可写:localhost或127.0.0.1。
port –为数据库的监听端口,需要看安装时的配置,缺省为3306。
databasename –数据库的名字。
举例如果要访问本地的数据库allandb,端口1433,那么URL写法如下:
jdbc:mysql://localhost:3306/allandb
下载地址:http://dev.mysql.com/downloads/connector/j/
Access数据库
驱动程序包名:该驱动程序包含在JavaSE中,不需要额外安装。
驱动类的名字:sun.jdbc.odbc.JdbcOdbcDriver
JDBC URL:jdbc:odbc:datasourcename
说明:该驱动只能工作在Windows系统中,首先需要在操作系统中建立一个可以访问Access数据库的本地数据源(ODBC),如果名字为allandb,那么URL写法如下:
jdbc:odbc:allandb
PreparedStatement接口:
预编译的sql语句对象
作用: 解决了书写sql语句时一些特殊的字符与sql保留字符冲突的问题,非常方便
/**
*知识点:
*PreparedStatement接口及方法的使用
*程序目标:
*java文件:
*PreparedInsert.java:连接数据库,插入一条数据
*JdbcUtil.java:实现一个工具类,功能:1.连接数据库 2.关闭资源
*/
package moudule1.preparedstatement;
import java.sql.*;
import moudule1.com.*;
public class PreparedInsert
{
public static void main(String[] args)
{
String sql="insert into yuchen_user (id,name) values (?,?)";
System.out.println(sql);
Connection con=null;
PreparedStatement ps=null;
try{
con=JdbcUtil.getConnection();
ps=con.prepareStatement(sql);
ps.setInt(1,2);
ps.setString(2,"zhangsan");
ps.executeUpdate();
ps.setInt(1,3);
ps.setString(2,"lisi");
ps.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,ps);
}
}
}
package moudule1.com;
import java.sql.*;
public class JdbcUtil{
public static Connection getConnection() throws Exception{
Class.forName("oracle.jdbc.driver.OracleDriver");
return DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:name", "scott","tiger");
}
public static void close(Connection con,Statement st){
close(con);
close(st);
}
public static void close(Connection con,Statement st,ResultSet rs){
close(con,st);
close(rs);
}
public static void close(Connection con){
try{
con.close();
}catch(Exception e){
}
}
public static void close(Statement st){
try{
st.close();
}catch(Exception e){
}
}
public static void close(ResultSet rs){
try{
rs.close();
}catch(Exception e){
}
}
}
数据库的增删改查的例子:
/**
*知识点:
*JDBC+SQL+ORACLE
*程序目标:
*UserDao.java:实现了数据库的增删改查
*JdbcUtil.java:工具类,有连库和关闭资源的方法
*/
package moudule1.idus;
import java.sql.*;
import moudule1.com.*;
public class UserDao{
private String sql;
private Connection con;
private Statement st;
private ResultSet rs;
public UserDao(){
sql=null;
con=null;
st=null;
rs=null;
}
public void insert(){
sql="insert into yuchen_user (id,name) values(";
sql+="4,'zhouwu')";
System.out.println(sql);
try{
con=JdbcUtil.getConnection();
st=con.createStatement();
st.executeUpdate(sql);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,st);
}
}
public void delete(){
sql="delete from yuchen_user where id=2";
System.out.println(sql);
try{
con=JdbcUtil.getConnection();
st=con.createStatement();
st.executeUpdate(sql);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,st);
}
}
public void update(){
sql="update yuchen_user set name='liumang' where id=1";
System.out.println(sql);
try{
con=JdbcUtil.getConnection();
st=con.createStatement();
st.executeUpdate(sql);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,st);
}
}
public void select(){
sql="select * from yuchen_user";
System.out.println(sql);
try{
con=JdbcUtil.getConnection();
st=con.createStatement();
rs=st.executeQuery(sql);
while(rs.next()){
System.out.println(rs.getInt(1));
System.out.println(rs.getString(2));
}
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,st,rs);
}
}
public static void main(String[] args){
UserDao ud=new UserDao();
ud.select();
ud.insert();
ud.select();
ud.update();
ud.select();
ud.delete();
ud.select();
}
}
一些常用的方法:
/**
*知识点:
*execute方法,getResultSet(),getUpdateCount()
*程序目标:
*JdbcUtil.java:工具类,连接数据库,关闭资源
*sqlExecutor.java:命令行参数输入sql语句,并执行该语句
*/
package moudule1.fangfa;
import java.sql.*;
import moudule1.com.*;
public class sqlExecutor{
public static void main(String[] args){
Connection con=null;
Statement st=null;
try{
con=JdbcUtil.getConnection();
st=con.createStatement();
boolean str=st.execute(args[0]);
if(str){
ResultSet rs=st.getResultSet();
while(rs.next()){
System.out.println(rs.getInt("id")+":"+rs.getString("name"));
}
rs.close();
}else{
int row=st.getUpdateCount();
System.out.println(row);
}
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtil.close(con,st);
}
}
}
2. 补充
JDBC连接MySQL
加载及注册JDBC驱动程序
Class.forName("com.mysql.jdbc.Driver");
Class.forName("com.mysql.jdbc.Driver").newInstance();
JDBC URL 定义驱动程序与数据源之间的连接
标准语法:
<protocol(主要通讯协议)>:<subprotocol(次要通讯协议,即驱动程序名称)>:<data source identifier(数据源)>
MySQL的JDBC URL格式:
jdbc:mysql//[hostname][:port]/[dbname][?param1=value1][¶m2=value2]….
示例:jdbc:mysql://localhost:3306/sample_db?user=root&password=your_password
常见参数:
user 用户名
password 密码
autoReconnect 联机失败,是否重新联机(true/false)
maxReconnect 尝试重新联机次数
initialTimeout 尝试重新联机间隔
maxRows 传回最大行数
useUnicode 是否使用Unicode字体编码(true/false)
characterEncoding 何种编码(GB2312/UTF-8/…)
relaxAutocommit 是否自动提交(true/false)
capitalizeTypeNames 数据定义的名称以大写表示
建立连接对象
String url="jdbc:mysql://localhost:3306/sample_db?user=root&password=your_password";
Connection con = DriverManager.getConnection(url);
建立SQL陈述式对象(Statement Object)
Statement stmt = con.createStatement();
执行SQL语句
executeQuery()
String query = "select * from test";
ResultSet rs=stmt.executeQuery(query);
结果集ResultSet
while(rs.next())
{rs.getString(1);rs.getInt(2);}
executeUpdate()
String upd="insert into test (id,name) values(1001,xuzhaori)";
int con=stmt.executeUpdate(upd);
execute()
示例:
try{
}
catch(SQLException sqle)
{
}
finally
{
}
Java类型和SQL类型 技术手册P421
PreparedStatement(预编语句)
PreparedStatement stmt = conn.prepareStatement("insert into test(id,name)values(?,?)");
stmt.setInt(1,id);
stmt.setString(2,name);
注:一旦设定语句的参数值后,就可以多次执行改语句,直到调用clearParameters()方法将他清除为止
CallableStatement(预储程序)技术手册P430
JDBC2.0使用
ResultSet对象中的光标上下自由移动
Statement stmt = con.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs=stmt.executeQuery("select * from test");
public Statement createStatement(int resultSetType,int resultSetConcuttency) throws SQLException
resultSetType
TYPE_FORWARD_ONLY 只能使用next()方法。
TYPE_SCROLL_SENSITIVE 可以上下移动,可以取得改变后的值。
TYPE_SCROLL_INSENSITIVE 可以上下移动。
resultSetConcuttency
CONCUR_READ_ONLY 只读
CONCUR_UPDATABLE ResultSet对象可以执行数据库的新增、修改、和移除
直接使用ResultSet对象执行更新数据
新增数据
Statement stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_PUDATABLE);
ResultSet uprs=stmt.executeQuery("select * from test");
uprs.moveToInsertRow();
uprs.updateInt(1,1001);
uprs.updateString(2,"许召日");
uprs.insertRow;
更新数据
Statement stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_PUDATABLE);
ResultSet uprs=stmt.executeQuery("select * from test");
uprs.last();
uprs.updateString("name","xuzhaori");
uprs.updateRow;
删除数据
Statement stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_PUDATABLE);
ResultSet uprs=stmt.executeQuery("select * from test");
uprs.absolute(4);
uprs.deleteRow();
批处理
con.setAutoCommit(false); 关闭自动认可模式
Statement stmt=con.createStatement();
int[] rows;
stmt.addBatch("insert into test values(1001,xuzhaori)");
stmt.addBatch("insert into test values(1002,xuyalin)");
rows=stmt.executeBatch();
con.commit(); 没有任何错误,执行批处理stmt.executeBatch();
JNDI-数据源(Data Source)与连接池(Connection Pool)
Tomcat的JDBC数据源设置 技术手册P439
连接池工具-Proxool Var 0.8.3 技术手册P446
设置web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--<?xml version="1.0" encoding="GB2312"?>-->
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
….
<servlet>
<servlet-name>ServletConfigurator</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
<init-param>
<param-name>propertyFile</param-name>
<param-value>WEB-INF/classes/Proxool.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
后端统计端口添加下列
<servlet>
<servlet-name>Admin</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Admin</servlet-name>
<url-pattern>/Admin</url-pattern>
</servlet-mapping>
….
</web-app>
配置Proxool.properties
jdbc-0.proxool.alias=JSPBook
jdbc-0.proxool.driver-class=com.mysql.jdbc.Driver
jdbc-0.proxool.driver-url=jdbc:mysql://localhost:3306/sample_db?user=root&password=browser&useUnicode=true&characterEncoding=UTF-8
jdbc-0.proxool.maximum-connection-count=10
jdbc-0.proxool.prototype-count=4
jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE
jdbc-0.proxool.verbose=true
jdbc-0.proxool.statistics=10s,1m,1d 后端统计接口添加此行
jdbc-0.proxool.statistics-log-level=DEBUG
使用Proxool连接池
Connection con = DriverManager.getConnection("proxool.JSPBook");
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
String query = "SELECT * FROM employee";
ResultSet rs = stmt.executeQuery(query);
**********************************************
1. MySQL(http://www.mysql.com)mm.mysql-2.0.2-bin.jar
Class.forName( "org.gjt.mm.mysql.Driver" );
cn = DriverManager.getConnection( "jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName", sUsr, sPwd );
2. PostgreSQL(http://www.de.postgresql.org)pgjdbc2.jar
Class.forName( "org.postgresql.Driver" );
cn = DriverManager.getConnection( "jdbc:postgresql://MyDbComputerNameOrIP/myDatabaseName", sUsr, sPwd );
3. Oracle(http://www.oracle.com/ip/deploy/database/oracle9i/)classes12.zip
Class.forName( "oracle.jdbc.driver.OracleDriver" );
cn = DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd );
4. Sybase(http://jtds.sourceforge.net)jconn2.jar
Class.forName( "com.sybase.jdbc2.jdbc.SybDriver" );
cn = DriverManager.getConnection( "jdbc:sybase:Tds:MyDbComputerNameOrIP:2638", sUsr, sPwd );
//(Default-Username/Password: "dba"/"sql")
5. Microsoft SQLServer(http://jtds.sourceforge.net)
Class.forName( "net.sourceforge.jtds.jdbc.Driver" );
cn = DriverManager.getConnection( "jdbc:jtds:sqlserver://MyDbComputerNameOrIP:1433/master", sUsr, sPwd );
6. Microsoft SQLServer(http://www.microsoft.com)
Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" );
cn = DriverManager.getConnection( "jdbc:microsoft:sqlserver://MyDbComputerNameOrIP:1433;databaseName=master", sUsr, sPwd );
7. ODBC
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
Connection cn = DriverManager.getConnection( "jdbc:odbc:" + sDsn, sUsr, sPwd );
8.DB2(新添加)
Class.forName("com.ibm.db2.jdbc.net.DB2Driver");
String url="jdbc:db2://192.9.200.108:6789/SAMPLE"
cn = DriverManager.getConnection( url, sUsr, sPwd );
9.Microsoft SQL Server series (6.5, 7.x and 2000) and Sybase 10
JDBC Name: jTDS
URL: http://jtds.sourceforge.net/
Version: 0.5.1
Download URL: http://sourceforge.net/project/showfiles.php?group_id=33291
语法:
Class.forName("net.sourceforge.jtds.jdbc.Driver ");
Connection con = DriverManager.getConnection("jdbc:jtds:sqlserver://host:port/database","user","password");
or
Connection con = DriverManager.getConnection("jdbc:jtds:sybase://host:port/database","user","password");
10.Postgresql
JDBC Name: PostgreSQL JDBC
URL: http://jdbc.postgresql.org/
Version: 7.3.3 build 110
Download URL: http://jdbc.postgresql.org/download.html
语法:
Class.forName("org.postgresql.Driver");
Connection con=DriverManager.getConnection("jdbc:postgresql://host:port/database","user","password");
11.IBM AS400主机在用的JDBC语法
有装V4R4以上版本的Client Access Express
可以在C:/Program Files/IBM/Client Access/jt400/lib
找到 driver 档案 jt400.zip,并更改扩展名成为 jt400.jar
语法:
java.sql.DriverManager.registerDriver (new com.ibm.as400.access.AS400JDBCDriver ());
Class.forName("com.ibm.as400.access.AS400JDBCConnection");
con = DriverManager.getConnection("jdbc:as400://IP","user","password");
12.informix
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url =
"jdbc:informix-sqli://123.45.67.89:1533/testDB:INFORMIXSERVER=myserver;
user=testuser;password=testpassword";
Lib:jdbcdrv.zip<br><br>Class.forName( "com.sybase.jdbc.SybDriver" )
url="jdbc:sybase:Tds:127.0.0.1:2638/asademo";
SybConnection connection= (SybConnection)DriverManager.getConnection(url,"dba","sql");
13.SAP DB
Class.forName ("com.sap.dbtech.jdbc.DriverSapDB");
java.sql.Connection connection = java.sql.DriverManager.getConnection ( "jdbc:sapdb://" + host + "/" + database_name,user_name, password)
14.InterBase
String url = "jdbc:interbase://localhost/e:/testbed/database/employee.gdb";
Class.forName("interbase.interclient.Driver");
//Driver d = new interbase.interclient.Driver (); /* this will also work if you do not want the line above */
Connection conn = DriverManager.getConnection( url, "sysdba", "masterkey" );
15.HSqlDB
url: http://hsqldb.sourceforge.net/
driver: org.hsqldb.jdbcDriver
连接方式有4种,分别为:
con-str(内存): jdbc:hsqldb.
con-str(本地): jdbc:hsqldb:/path/to/the/db/dir
con-str(http): jdbc:hsqldb:http://dbsrv
con-str(hsql): jdbc:hsqldb:hsql://dbsrv
********************************************************************************************
随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机应用程序已从传统的桌面应用转到Web应用。基于B/S(Browser/Server)架构的3层开发模式逐渐取代C/S(Client/Server)架构的开发模式,成为开发企业级应用和电子商务普遍采用的技术。在Web应用开发的早期,主要使用的技术是CGI﹑ASP﹑PHP等。之后,Sun公司推出了基于Java语言的Servlet+Jsp+JavaBean技术。相比传统的开发技术,它具有跨平台﹑安全﹑有效﹑可移植等特性,这使其更便于使用和开发。
Java应用程序访问数据库的基本原理
在Java语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁,
即Java语言通过JDBC技术访问数据库。JDBC是一种“开放”的方案,它为数据库应用开发人员﹑数据库前台工具开发人员提供了一种标准的应用程序设计接口,使开发人员可以用纯Java语言编写完整的数据库应用程序。JDBC提供两种API,分别是面向开发人员的API和面向底层的JDBC驱动程序API,底层主要通过直接的JDBC驱动和JDBC-ODBC桥驱动实现与数据库的连接。
一般来说,Java应用程序访问数据库的过程(如图1所示)是:
①装载数据库驱动程序;
②通过JDBC建立数据库连接;
③访问数据库,执行SQL语句;
④断开数据库连接。
图1 Java数据库访问机制
JDBC作为一种数据库访问技术,具有简单易用的优点。但使用这种模式进行Web应用
程序开发,存在很多问题:首先,每一次Web请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费0.05s~1s的时间,而且系统还要分配内存资源。这个时间对于一次或几次数据库操作,或许感觉不出系统有多大的开销。可是对于现在的Web应用,尤其是大型电子商务网站,同时有几百人甚至几千人在线是很正常的事。在这种情况下,频繁的进行数据库连接操作势必占用很多的系统资源,网站的响应速度必定下降,严重的甚至会造成服务器的崩溃。不是危言耸听,这就是制约某些电子商务网站发展的技术瓶颈问题。其次,对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将不得不重启数据库。还有,这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。
数据库连接池(connection pool)的工作原理
1、基本概念及原理
由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理。我们知道,
对于共享资源,有一个很著名的设计模式:资源池(Resource Pool)。该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。连接池的基本工作原理见下图2。
图2 连接池的基本工作原理
2、服务器自带的连接池
JDBC的API中没有提供连接池的方法。一些大型的WEB应用服务器如BEA的WebLogic和IBM的WebSphere等提供了连接池的机制,但是必须有其第三方的专用类方法支持连接池的用法。
连接池关键问题分析
1、并发问题
为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为Java语言自身提供了对并发管理的支持,使用synchronized关键字即可确保线程是同步的。使用方法为直接在类方法前面加上synchronized关键字,如:
public synchronized Connection getConnection()
2、多数据库服务器和多用户
对于大型的企业级应用,常常需要同时连接不同的数据库(如连接Oracle和Sybase)。如何连接不同的数据库呢?我们采用的策略是:设计一个符合单例模式的连接池管理类,在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url地址(<poolName.url>)﹑用户名(<poolName.user>)﹑密码(<poolName.password>)等信息。如tx.url=192.168.1.123:5000/tx_it,tx.user=cyl,tx.password=123456。根据资源文件提供的信息,创建多个连接池类的实例,每一个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字,通过不同的名字来管理不同的连接池。
对于同一个数据库有多个用户使用不同的名称和密码访问的情况,也可以通过资源文件处理,即在资源文件中设置多个具有相同url地址,但具有不同用户名和密码的数据库连接信息。
3、事务处理
我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-ALL-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。
在Java语言中,Connection类本身提供了对事务的支持,可以通过设置Connection的AutoCommit属性为false,然后显式的调用commit或rollback方法来实现。但要高效的进行Connection复用,就必须提供相应的事务支持机制。可采用每一个事务独占一个连接来实现,这种方法可以大大降低事务管理的复杂性。
4、连接池的分配与释放
连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。
对于连接的管理可使用空闲池。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接。如果有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的判断,如果可用就分配给用户,如不可用就把这个连接从空闲池删掉,重新检测空闲池是否还有连接);如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数(maxConn),如果没有达到,就新建一个连接,如果已经达到,就等待一定的时间(timeout)。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户,如果等待时间超过预定时间timeout,则返回空值(null)。系统对已经分配出去正在使用的连接只做计数,当使用完后再返还给空闲池。对于空闲连接的状态,可开辟专门的线程定时检测,这样会花费一定的系统开销,但可以保证较快的响应速度。也可采取不开辟专门线程,只是在分配前检测的方法。
5、连接池的配置与维护
连接池中到底应该放置多少连接,才能使系统的性能最佳?系统可采取设置最小连接数(minConn)和最大连接数(maxConn)来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过反复测试,找到最佳点。
如何确保连接池中的最小连接数呢?有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。
连接池的实现
1、连接池模型
本文讨论的连接池包括一个连接池类(DBConnectionPool)和一个连接池管理类(DBConnetionPoolManager)和一个配置文件操作类(ParseDSConfig)。连接池类是对某一数据库所有连接的“缓冲池”,主要实现以下功能:①从连接池获取或创建可用连接;②使用完毕之后,把连接返还给连接池;③在系统关闭前,断开所有连接并释放连接占用的系统资源;④还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。(5)当多数据库时,且数据库是动态增加的话,将会加到配置文件中。
连接池管理类是连接池类的外覆类(wrapper),符合单例模式,即系统中只能有一个连接池管理类的实例。其主要用于对多个连接池对象的管理,具有以下功能:①装载并注册特定数据库的JDBC驱动程序;②根据属性文件给定的信息,创建连接池对象;③为方便管理多个连接池对象,为每一个连接池对象取一个名字,实现连接池名字与其实例之间的映射;④跟踪客户使用连接情况,以便需要是关闭连接释放资源。连接池管理类的引入主要是为了方便对多个连接池的使用和管理,如系统需要连接不同的数据库,或连接相同的数据库但由于安全性问题,需要不同的用户使用不同的名称和密码。
2、连接池实现(经过本人改版,可以适用多数据库类型的应用以及一种数据库类型多个数据库且数据 库的数量可以动态增加的应用程序)
1),DBConnectionPool.java 数据库连接池类
2),DBConnectionManager .java 数据库管理类
3),DSConfigBean .java 单个数据库连接信息Bean
4),ParseDSConfig.java 操作多(这个'多'包括不同的数据库和同一种数据库有多个数据库)
数据 配置文件xml
5),ds.config.xml 数据库配置文件xml
原代码如下:
DBConnectionPool.java
----------------------------------------------------------
/**
* 数据库连接池类
*/
package com.chunkyo.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Timer;
/**
* @author chenyanlin
*
*/
public class DBConnectionPool implements TimerListener {
private Connection con=null;
private int inUsed=0; //使用的连接数
private ArrayList freeConnections = new ArrayList();//容器,空闲连接
private int minConn; //最小连接数
private int maxConn; //最大连接
private String name; //连接池名字
private String password; //密码
private String url; //数据库连接地址
private String driver; //驱动
private String user; //用户名
public Timer timer; //定时
/**
*
*/
public DBConnectionPool() {
// TODO Auto-generated constructor stub
}
/**
* 创建连接池
* @param driver
* @param name
* @param URL
* @param user
* @param password
* @param maxConn
*/
public DBConnectionPool(String name, String driver,String URL, String user, String password, int maxConn)
{
this.name=name;
this.driver=driver;
this.url=URL;
this.user=user;
this.password=password;
this.maxConn=maxConn;
}
/**
* 用完,释放连接
* @param con
*/
public synchronized void freeConnection(Connection con)
{
this.freeConnections.add(con);//添加到空闲连接的末尾
this.inUsed--;
}
/**
* timeout 根据timeout得到连接
* @param timeout
* @return
*/
public synchronized Connection getConnection(long timeout)
{
Connection con=null;
if(this.freeConnections.size()>0)
{
con=(Connection)this.freeConnections.get(0);
if(con==null)con=getConnection(timeout); //继续获得连接
}
else
{
con=newConnection(); //新建连接
}
if(this.maxConn==0||this.maxConn<this.inUsed)
{
con=null;//达到最大连接数,暂时不能获得连接了。
}
if(con!=null)
{
this.inUsed++;
}
return con;
}
/**
*
* 从连接池里得到连接
* @return
*/
public synchronized Connection getConnection()
{
Connection con=null;
if(this.freeConnections.size()>0)
{
con=(Connection)this.freeConnections.get(0);
this.freeConnections.remove(0);//如果连接分配出去了,就从空闲连接里删除
if(con==null)con=getConnection(); //继续获得连接
}
else
{
con=newConnection(); //新建连接
}
if(this.maxConn==0||this.maxConn<this.inUsed)
{
con=null;//等待 超过最大连接时
}
if(con!=null)
{
this.inUsed++;
System.out.println("得到 "+this.name+" 的连接,现有"+inUsed+"个连接在使用!");
}
return con;
}
/**
*释放全部连接
*
*/
public synchronized void release()
{
Iterator allConns=this.freeConnections.iterator();
while(allConns.hasNext())
{
Connection con=(Connection)allConns.next();
try
{
con.close();
}
catch(SQLException e)
{
e.printStackTrace();
}
}
this.freeConnections.clear();
}
/**
* 创建新连接
* @return
*/
private Connection newConnection()
{
try {
Class.forName(driver);
con=DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("sorry can't find db driver!");
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.out.println("sorry can't create Connection!");
}
return con;
}
/**
* 定时处理函数
*/
public synchronized void TimerEvent()
{
//暂时还没有实现以后会加上的
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
/**
* @return the driver
*/
public String getDriver() {
return driver;
}
/**
* @param driver the driver to set
*/
public void setDriver(String driver) {
this.driver = driver;
}
/**
* @return the maxConn
*/
public int getMaxConn() {
return maxConn;
}
/**
* @param maxConn the maxConn to set
*/
public void setMaxConn(int maxConn) {
this.maxConn = maxConn;
}
/**
* @return the minConn
*/
public int getMinConn() {
return minConn;
}
/**
* @param minConn the minConn to set
*/
public void setMinConn(int minConn) {
this.minConn = minConn;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
/**
* @return the url
*/
public String getUrl() {
return url;
}
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}
/**
* @return the user
*/
public String getUser() {
return user;
}
/**
* @param user the user to set
*/
public void setUser(String user) {
this.user = user;
}
}
DBConnectionManager .java
------------------------------------------
/**
* 数据库连接池管理类
*/
package com.chunkyo.db;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;
import com.chunkyo.db.ParseDSConfig;
import com.chunkyo.db.DSConfigBean;
import com.chunkyo.db.DBConnectionPool;
/**
* @author chenyanlin
*
*/
public class DBConnectionManager {
static private DBConnectionManager instance;//唯一数据库连接池管理实例类
static private int clients; //客户连接数
private Vector drivers = new Vector();//驱动信息
private Hashtable pools=new Hashtable();//连接池
/**
* 实例化管理类
*/
public DBConnectionManager() {
// TODO Auto-generated constructor stub
this.init();
}
/**
* 得到唯一实例管理类
* @return
*/
static synchronized public DBConnectionManager getInstance()
{
if(instance==null)
{
instance=new DBConnectionManager();
}
return instance;
}
/**
* 释放连接
* @param name
* @param con
*/
public void freeConnection(String name, Connection con)
{
DBConnectionPool pool=(DBConnectionPool)pools.get(name);//根据关键名字得到连接池
if(pool!=null)
pool.freeConnection(con);//释放连接
}
/**
* 得到一个连接根据连接池的名字name
* @param name
* @return
*/
public Connection getConnection(String name)
{
DBConnectionPool pool=null;
Connection con=null;
pool=(DBConnectionPool)pools.get(name);//从名字中获取连接池
con=pool.getConnection();//从选定的连接池中获得连接
if(con!=null)
System.out.println("得到连接。。。");
return con;
}
/**
* 得到一个连接,根据连接池的名字和等待时间
* @param name
* @param time
* @return
*/
public Connection getConnection(String name, long timeout)
{
DBConnectionPool pool=null;
Connection con=null;
pool=(DBConnectionPool)pools.get(name);//从名字中获取连接池
con=pool.getConnection(timeout);//从选定的连接池中获得连接
System.out.println("得到连接。。。");
return con;
}
/**
* 释放所有连接
*/
public synchronized void release()
{
Enumeration allpools=pools.elements();
while(allpools.hasMoreElements())
{
DBConnectionPool pool=(DBConnectionPool)allpools.nextElement();
if(pool!=null)pool.release();
}
pools.clear();
}
/**
* 创建连接池
* @param props
*/
private void createPools(DSConfigBean dsb)
{
DBConnectionPool dbpool=new DBConnectionPool();
dbpool.setName(dsb.getName());
dbpool.setDriver(dsb.getDriver());
dbpool.setUrl(dsb.getUrl());
dbpool.setUser(dsb.getUsername());
dbpool.setPassword(dsb.getPassword());
dbpool.setMaxConn(dsb.getMaxconn());
System.out.println("ioio:"+dsb.getMaxconn());
pools.put(dsb.getName(), dbpool);
}
/**
* 初始化连接池的参数
*/
private void init()
{
//加载驱动程序
this.loadDrivers();
//创建连接池
Iterator alldriver=drivers.iterator();
while(alldriver.hasNext())
{
this.createPools((DSConfigBean)alldriver.next());
System.out.println("创建连接池。。。");
}
System.out.println("创建连接池完毕。。。");
}
/**
* 加载驱动程序
* @param props
*/
private void loadDrivers()
{
ParseDSConfig pd=new ParseDSConfig();
//读取数据库配置文件
drivers=pd.readConfigInfo("ds.config.xml");
System.out.println("加载驱动程序。。。");
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
----------------------------------------
DSConfigBean.java
----------------------------------------
/**
* 配置文件Bean类
*/
package com.chunkyo.db;
/**
* @author chenyanlin
*
*/
public class DSConfigBean {
private String type =""; //数据库类型
private String name =""; //连接池名字
private String driver =""; //数据库驱动
private String url =""; //数据库url
private String username =""; //用户名
private String password =""; //密码
private int maxconn =0; //最大连接数
/**
*
*/
public DSConfigBean() {
// TODO Auto-generated constructor stub
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
/**
* @return the driver
*/
public String getDriver() {
return driver;
}
/**
* @param driver the driver to set
*/
public void setDriver(String driver) {
this.driver = driver;
}
/**
* @return the maxconn
*/
public int getMaxconn() {
return maxconn;
}
/**
* @param maxconn the maxconn to set
*/
public void setMaxconn(int maxconn) {
this.maxconn = maxconn;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
/**
* @return the type
*/
public String getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(String type) {
this.type = type;
}
/**
* @return the url
*/
public String getUrl() {
return url;
}
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
}
-----------------------------------------------------
ParseDSConfig.java
-----------------------------------------------------
/**
* 操作配置文件类 读 写 修改 删除等操作
*/
package com.chunkyo.db;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Vector;
import java.util.Iterator;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
/**
* @author chenyanlin
*
*/
public class ParseDSConfig {
/**
* 构造函数
*/
public ParseDSConfig() {
// TODO Auto-generated constructor stub
}
/**
* 读取xml配置文件
* @param path
* @return
*/
public Vector readConfigInfo(String path)
{
String rpath=this.getClass().getResource("").getPath().substring(1)+path;
Vector dsConfig=null;
FileInputStream fi = null;
try
{
fi=new FileInputStream(rpath);//读取路径文件
dsConfig=new Vector();
SAXBuilder sb=new SAXBuilder();
Document doc=sb.build(fi);
Element root=doc.getRootElement();
List pools=root.getChildren();
Element pool=null;
Iterator allPool=pools.iterator();
while(allPool.hasNext())
{
pool=(Element)allPool.next();
DSConfigBean dscBean=new DSConfigBean();
dscBean.setType(pool.getChild("type").getText());
dscBean.setName(pool.getChild("name").getText());
System.out.println(dscBean.getName());
dscBean.setDriver(pool.getChild("driver").getText());
dscBean.setUrl(pool.getChild("url").getText());
dscBean.setUsername(pool.getChild("username").getText());
dscBean.setPassword(pool.getChild("password").getText());
dscBean.setMaxconn(Integer.parseInt(pool.getChild("maxconn").getText()));
dsConfig.add(dscBean);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try {
fi.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return dsConfig;
}
/**
*修改配置文件 没时间写 过段时间再贴上去 其实一样的
*/
public void modifyConfigInfo(String path,DSConfigBean dsb) throws Exception
{
String rpath=this.getClass().getResource("").getPath().substring(1)+path;
FileInputStream fi=null; //读出
FileOutputStream fo=null; //写入
}
/**
*增加配置文件
*
*/
public void addConfigInfo(String path,DSConfigBean dsb)
{
String rpath=this.getClass().getResource("").getPath().substring(1)+path;
FileInputStream fi=null;
FileOutputStream fo=null;
try
{
fi=new FileInputStream(rpath);//读取xml流
SAXBuilder sb=new SAXBuilder();
Document doc=sb.build(fi); //得到xml
Element root=doc.getRootElement();
List pools=root.getChildren();//得到xml子树
Element newpool=new Element("pool"); //创建新连接池
Element pooltype=new Element("type"); //设置连接池类型
pooltype.setText(dsb.getType());
newpool.addContent(pooltype);
Element poolname=new Element("name");//设置连接池名字
poolname.setText(dsb.getName());
newpool.addContent(poolname);
Element pooldriver=new Element("driver"); //设置连接池驱动
pooldriver.addContent(dsb.getDriver());
newpool.addContent(pooldriver);
Element poolurl=new Element("url");//设置连接池url
poolurl.setText(dsb.getUrl());
newpool.addContent(poolurl);
Element poolusername=new Element("username");//设置连接池用户名
poolusername.setText(dsb.getUsername());
newpool.addContent(poolusername);
Element poolpassword=new Element("password");//设置连接池密码
poolpassword.setText(dsb.getPassword());
newpool.addContent(poolpassword);
Element poolmaxconn=new Element("maxconn");//设置连接池最大连接
poolmaxconn.setText(String.valueOf(dsb.getMaxconn()));
newpool.addContent(poolmaxconn);
pools.add(newpool);//将child添加到root
Format format = Format.getPrettyFormat();
format.setIndent("");
format.setEncoding("utf-8");
XMLOutputter outp = new XMLOutputter(format);
fo = new FileOutputStream(rpath);
outp.output(doc, fo);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
}
}
/**
*删除配置文件
*/
public void delConfigInfo(String path,String name)
{
String rpath=this.getClass().getResource("").getPath().substring(1)+path;
FileInputStream fi = null;
FileOutputStream fo=null;
try
{
fi=new FileInputStream(rpath);//读取路径文件
SAXBuilder sb=new SAXBuilder();
Document doc=sb.build(fi);
Element root=doc.getRootElement();
List pools=root.getChildren();
Element pool=null;
Iterator allPool=pools.iterator();
while(allPool.hasNext())
{
pool=(Element)allPool.next();
if(pool.getChild("name").getText().equals(name))
{
pools.remove(pool);
break;
}
}
Format format = Format.getPrettyFormat();
format.setIndent("");
format.setEncoding("utf-8");
XMLOutputter outp = new XMLOutputter(format);
fo = new FileOutputStream(rpath);
outp.output(doc, fo);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try {
fi.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ParseDSConfig pd=new ParseDSConfig();
String path="ds.config.xml";
pd.readConfigInfo(path);
//pd.delConfigInfo(path, "tj012006");
DSConfigBean dsb=new DSConfigBean();
dsb.setType("oracle");
dsb.setName("yyy004");
dsb.setDriver("org.oracle.jdbc");
dsb.setUrl("jdbc:oracle://localhost");
dsb.setUsername("sa");
dsb.setPassword("");
dsb.setMaxconn(1000);
pd.addConfigInfo(path, dsb);
pd.delConfigInfo(path, "yyy001");
}
}
--------------------------------------
ds.config.xml 配置文件
--------------------------------------
<ds-config>
<pool>
<type>mysql</type>
<name>user</name>
<driver>com.mysql.jdbc.driver</driver>
<url>jdbc:mysql://localhost:3306/user</url>
<username>sa</username>
<password>123456</password>
<maxconn>100</maxconn>
</pool>
<pool>
<type>mysql</type>
<name>user2</name>
<driver>com.mysql.jdbc.driver</driver>
<url>jdbc:mysql://localhost:3306/user2</url>
<username>sa</username>
<password>1234</password>
<maxconn>10</maxconn>
</pool>
<pool>
<type>sql2000</type>
<name>books</name>
<driver>com.microsoft.sqlserver.driver</driver>
<url>jdbc:sqlserver://localhost:1433/books:databasename=books</url>
<username>sa</username>
<password></password>
<maxconn>100</maxconn>
</pool>
</ds-config>
3. 连接池的使用
1。Connection的获得和释放
DBConnectionManager connectionMan=DBConnectionManager .getInstance();//得到唯一实例
//得到连接
String name="mysql";//从上下文得到你要访问的数据库的名字
Connection con=connectionMan.getConnection(name);
//使用
。。。。。。。
// 使用完毕
connectionMan.freeConnection(name,con);//释放,但并未断开连接
2。数据库连接的动态增加和连接池的动态增加
1。调用xml操作增加类
2。重新实例华连接池管理池类