slide1
Download
Skip this Video
Download Presentation
第十讲

Loading in 2 Seconds...

play fullscreen
1 / 67

第十讲 - PowerPoint PPT Presentation


  • 195 Views
  • Uploaded on

第十讲. 课  题  JDBC 与数据库( JDBC 与 SQL 语句、存储过程的应用) 目的要求 掌握 JDBC 存取各种不同数据库的方法   教学重点 掌握 JDBC 与不同数据库的连接字符串、连接池 教学难点 JSP 如何存取存储过程中输入参数、输出参数、输入输出 参数 教学课时 4 (含 2 课时上机) 教学方法 讲解、示例与启发式教学相结合  . 教学内容和步骤 10.1 JDBC 与数据库编程 10.1.1 JDBC 的 Driver 可分为以下四种类型

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' 第十讲' - eytan


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide2

课  题 JDBC与数据库(JDBC与SQL语句、存储过程的应用)

目的要求 掌握JDBC存取各种不同数据库的方法  

教学重点 掌握JDBC与不同数据库的连接字符串、连接池

教学难点 JSP如何存取存储过程中输入参数、输出参数、输入输出

参数

教学课时 4(含2课时上机)

教学方法 讲解、示例与启发式教学相结合  

slide3

教学内容和步骤

10.1 JDBC与数据库编程

10.1.1 JDBC的Driver可分为以下四种类型

(1)JDBC-ODBC Bridge和ODBC Driver

  这种驱动器器通过ODBC驱动器提供数据库连接。使用这种驱动器,要求每一台客户机都装入ODBC的驱动器。

(2)Native-API partly-Java Driver

  这种驱动器将JDBC指令转化成所连接使用的DBMS的操作形式。各客户机使用的数据库可能是Oracle,可能是Sybase,也可能是Access,都需要在客户机上装有相应DBMS的驱动程序。

slide4

(3)JDBC-Net All-Java Driver

  这种驱动器将JDBC指令转化成独立于DBMS的网络协议形式,再由服务器转化为特定DBMS的协议形式。有关DBMS的协议由各数据库厂商决定。这种驱动器可以联接到不同的数据库上,最为灵活。目前一些厂商已经开始添加JDBC的这种驱动器到他们已有的数据库中介产品中。要注意的是,为了支持广域网存取,需要增加有关安全性的措施,如防火墙等等。

slide5

(4)Native-protocol All-Java Driver

  这种驱动器将JDBC指令转化成网络协议后不再转换,由DBMS直接使用。相当于客户机直接与服务器联系,对局域网适用。

  在这四种驱动器中,后两类“纯Java”(All-Java)的驱动器效率更高,也更具有通用性。但目前第一、第二类驱动器比较容易获得,使用也较普遍。

10.1.2 关于JDBC Url

语法如下:

jdbc:<子协议>:<子名称>

slide6

<子协议>---驱动程序名称或数据库连接机制,子协议名称的典型例子就是ODBC ,如:jdbc:odbc:fff

<子名称>---一种标识数据库的方法。子名称可以依据不同的子协议而发生变化

如:jdbc:dbnet//womat:356//fff

ODBC子协议:

Jdbc:odbc:<数据源名称>[;<属性名>=<属性值>]

如:

jdbc:odbc:sqlconn:UID=sa;PWD=ww

slide7

10.2 JDBC编程

10.2.1 程序基本结构

一般的JDBC程序都完成三项功能:与数据库建立连接;传送SQL 声明以及对返回结果进行处理。下面我们通过一个具体例子说明这三项功能的实现过程。

例1: Creage.java给出了一个简单的JDBC程序,此程序执行后创建一张名为testTable的表,表中包括两个域,域名分别为id和name。

import java.net.URL;

import java.sql.*;

class Create{

public static void main (String[] args){

String url="jdbc:odbc:demo";

slide8

String query="CREATE TABLE testTable" + "(id INT,name CHAR(10))";

try{

//下载jdbc-odbc bridge 驱动器

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//关于此句参见下面Cyclone的注释

//与驱动器建立连接 ,这里可使用不同的特定驱动,如jdbcfororacle或jdbcforsqlserver

Connection con=DriverManager.getConnection(url,"user","password");

//创建一个Statement对象

Statement stmt=con.createStatement();

//执行SQL声明

stmt.executeUpdate(query);

slide9

System.out.println("Create successfully!");

//关闭 stm

stmt.close();

//关闭连接

con.close();

}catch(SQLException ex){

//SQL异常信息

System.out.println("\n***SQLException caught ***\n");

while(ex!=null){

System.out.println("SQLState:"+ex.getSQLState());

System.out.println("Message:"+ex.getMessage());

System.out.println("Vendor:"+ex.getErrorCode());

slide10

ex=ex.getNextException();

System.out.println("");

}

}catch(java.lang.Exception ex){

ex.printStackTrace();

}

}

}

2.2 Statement类及其子类

1)Statement接口

slide11

Statement stmt=con.createStatement();

//执行SQL声明

int count1=stmt.executeUpdate("INSERT INTO testTable(id,name) VALUES(1,\'wu\')");

int count2=stmt.executeUpdate("INSERT INTO testTable(id,name) VALUES(2,\'wang\')");

2)PreparedStatement接口

String data[][]={{"5","xu"},{"6","yan"}};

PreparedStatement pstmt=con.prepareStatement("INSERT INTO testTable (id,name) VALUES(?,?)");

slide12

//参数赋值,执行SQL声明

for (int i=0;i<data.length;i++){

pstmt.setInt(1,Integer.parseInt(data[i][0]));

pstmt.setString(2,data[i][1]);

pstmt.executeUpdate();

}

3)CallableStatement接口

CallableStatement cstmt=con.prepareCall("{call Search(?)}");

//参数赋值

cstmt.setInt(1,934678);

//执行储存过程。

cstmt.execute();

slide13

2.3 结果集ResultSet及ResultSetMetaData

String query = "SELECT * FROM testTable";

Statement stmt=con.createStatement();

//发出查询要求,获得结果集

ResultSet rs=stmt.executeQuery(query);

//显示结果集各行各列

System.out.println("The detail of testTable is:");

ResultSetMetaData rsmd=rs.getMetaData();

//获得结果集列数

in numCols=rsmd.getColumnCount();

//显示列标题

for(int i=1;i<=numCols;i++)

{

slide14

if(i>1) System.out.print(",");

System.out.print(rsmd.getColumnLabel(i));

}

System.out.println("");

//显示结果集信息

while(rs.next())

{

//显示一行

for(int i=1;i<=numCols;i++){

slide15

if(i>1) System.out.print(",");

System.out.print(rs.getString(i));

}

2.4 DatabaseMetaData

DatabaseMetaData dma = con.getMetaData();

//驱动器和URL信息

System.out.println("\nConnected to" + dma.getURL());

System.out.println("Driver" + dma.getDriverName());

System.out.println("Version" + dma.getDriverVersion()

slide16

//数据库信息

System.out.println("\nDataBase name:" + dma.getDatabaseProductName()+dma.getDatabaseProductVersion());

System.out.println("DataBase supports SQL keywords:\n\t" + dma.getSQLKeywords());

//数据库功能信息函数

dma.supportsANSI92EntryLevelSQL()

dma.supportsANSI92FullSQL()

dma.supportsStoredProcedures()

slide17

10.2.2 JDBC数据类型及类型转换

⑴ JDBC的数据类型

JDBC的sql包中除了与数据库连接有关的抽象接口及与驱动器有关的DriverManager、DriverPropertyInfo等类型外,还定义了若干数据类,用以代表数据库中可能用到的SQL类型。下面我们就对它们逐一进行简略介绍。

slide18

① sql.Date

sql包中的日期类Date是util包中Date类的子类,实际上也是util.Date类的子集。它只处理年月日,而忽略小时和分秒,用以代表SQL的DATE信息。

Date类的构造方法为:

public Date(int year, int mouth, int day)

其中参数格式同util.Date类的构造方法一样,年参数为所需设定的年份减去1900所得的整数值,月参数为0至11,日参数为1至31。如1998年1月23日所对应创建日期类的方法调用为:

slide19

Date d=new Date(98,0,23);

Date类还提供两个与String类互相转换的方法,分别是:

public static Date valueOf(String s)

将字符串类参数转换为日期类对象。其中String类参数S的格式为“年-月-日”,加“1997-04-12”。

public String toString()

将日期类对象转换为String类对象表示,同样采用“年-月-日”的格式。

slide20

 ② sql.Time

   该类是util.Date类的子类,也是它的一个子集。在Time类里,只处理小时和分秒,代表SQL的TIME类型。它与sql.Date合起来才表示完整的util.Date类信息。

Time类的构造方法为:

public Time(int hour,int minute,int second)

其中小时参数值为0至23,分秒参数取值均为0至59。

   与sql.Date一样,Time类也定义了两个与String类互相转换的函数ValueOf和String。不同的是String类对象的格式为“小时:分:秒”,如“12:26:06”。

slide21

 ③ sql.Timestamp

   这个类也是util.Date类的子类,其中除了包含年月日、小时和分秒和信息之外,还加入了纳秒信息(nanosecond),1纳秒即1毫微秒。Timestamp类用来代表SQL时间戳(Timestamp)类型信息。

Timestamp类的构造方法为:

public Timestamp(int year, int mouth, int date, int hour, int minute, int second, int nano)其中纳秒参数的取值从0至999,999,999,其余各参数同前。

Timestamp类特别定义了设置和获得纳秒信息的方法,分别是

public getnanos()

  获取时间戳的纳秒部分

public void setNanos(int n)

  以给定数值设置时间戳的纳秒部分

slide22

④ sql.Types

Types类是Object类的直接子类。在这个类中以静态常量的形式定义了可使用的SQL的数值类型。所有这些类型常量都以前缀

public final static int的形式标明是公有静态整数,且不可改动。具体的类型名和含义如表11.1所示。其中OTHER用来代表数据库定义的特殊数据,可以用getObject或setObject方法将其映射为一个Java的Object对象。

slide25

⑵ SQL与Java

  由于SQL数据类型与Java的数据类型不一致,因而在使用Java类型的应用程序与使用SQL类型的数据库之间,需要某种读写类型转换机制。实际上我们前面介绍的ResultSet类的“get”系列方法,Statement及其子类的“set“系列方法和registerOutParameter方法,都是这一转换机制的组成部分。

  需要进行的读写转换包括下面情况:

  从数据库中读取数值后,存放在ResultSet对象中的是SQL类型的数据。而调用“get”系列方法时,JDBC才将SQL类型转换为指定的Java类型。在一般情形下,SQL类型相对应的Java类型如表11-2所示。

slide26

⑵ SQL与Java

  由于SQL数据类型与Java的数据类型不一致,因而在使用Java类型的应用程序与使用SQL类型的数据库之间,需要某种读写类型转换机制。实际上我们前面介绍的ResultSet类的“get”系列方法,Statement及其子类的“set“系列方法和registerOutParameter方法,都是这一转换机制的组成部分。

  需要进行的读写转换包括下面情况:

  从数据库中读取数值后,存放在ResultSet对象中的是SQL类型的数据。而调用“get”系列方法时,JDBC才将SQL类型转换为指定的Java类型。在一般情形下,SQL类型相对应的Java类型如表11-2所示。

slide28

⑶ 字符类型

JDBC 字符串数据类型为 CHAR、VARCHAR 和 LONGVARCHAR。

slide30

⑷ 二进制字符串类型

JDBC 二进制字符串类型为 BINARY、VARBINARY 和 LONGVARBINARY。

slide32

⑸ 精确数字类型

JDBC 精确数字类型直接映射到其对应的 SQL Server类型。

slide34

⑹ 近似数字类型

JDBC 近似数值数据类型为 REAL、DOUBLE和 FLOAT。

slide35

⑺ 日期时间类型

JDBC TIMESTAMP 类型映射到 SQL Server datetime 和 smalldatetime 类型。datetime 类型以两个 4 字节整数进行存储。smalldatetime 类型可存放相同的信息(日期和时间),但精度较低,为两个 2 字节的小整数。

slide36

10.3 JDBC与数据库的连接字符串

⑴ 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 );

⑵ 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 );

slide37

⑶ Sybase(http://jtds.sourceforge.net)jconn2.jar

Class.forName( "com.sybase..jdbc.SybDriver" );

cn = DriverManager.getConnection( "jdbc:sybase:Tds:MyDbComputerNameOrIP:2638", sUsr, sPwd );

//(Default-Username/Password: "dba"/"sql")

⑷ 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 );

slide38

⑸ ODBC

Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );

Connection cn = DriverManager.getConnection( "jdbc:odbc:" + sDsn, sUsr, sPwd );

⑹ 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";

slide39

⑺ sybase

Class.forName( "com.sybase.jdbc.SybDriver" )

url="jdbc:sybase:Tds:127.0.0.1:2638/asademo";

SybConnection connection= (SybConnection)

DriverManager.getConnection(url,"dba","sql");

slide40

例2: queryBook.jsp

<%@page contentType="text/html;charset=gb2312"%>

<%@page language="java" import="java.sql.*,java.io.*"%>

<HTML>

<BODY>

<CENTER>

<FONT SIZE = 5 COLOR = blue>图书信息浏览</FONT>

<table border=3>

<tr><td><b><center>ID号</td> <td><b><center>书名</td>

<td><b><center>出版社</td> <td><b><center>价格</td></tr>

<%

slide41

Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();

Connection con=java.sql.DriverManager.getConnection("jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=jspdb","sa","");

Statement stmt=con.createStatement();

ResultSet rst=stmt.executeQuery("select * from book;");

while(rst.next())

{

slide42

out.println("<tr>");

out.println("<td>"+rst.getString("bkld")+"</td>");

out.println("<td>"+rst.getString("bkName")+"</td>");

out.println("<td>"+rst.getString("bkPublisher")+"</td>");

out.println("<td>"+rst.getFloat("bkPrice")+"元"+"</td>");

out.println("</tr>");

}

slide43

rst.close();

stmt.close();

con.close();

%>

</table>

</BODY>

</HTML>

slide44

10.4 连接池

⑴ 连接池原理

连接池技术的核心思想是:连接复用,通过建立一个数据库连接池以及一套连接使用、分配、管理策略,使得该连接池中的连接可以得到高效、安全的复用,避免了数据库连接频繁建立、关闭的开销。另外,由于对JDBC中的原始连接进行了封装,从而方便了数据库应用对于连接的使用(特别是对于事务处理),提高了开发效率,也正是因为这个封装层的存在,隔离了应用的本身的处理逻辑和具体数据库访问逻辑,使应用本身的复用成为可能。连接池主要由三部分组成:连接池的建立、连接池中连接的使用管理、连接池的关闭。

slide45

⑵ 连接池的管理

连接池管理策略是连接池机制的核心。当连接池建立后,如何对连接池中的连接进行管理,解决好连接池内连接的分配和释放,对系统的性能有很大的影响。连接的合理分配、释放可提高连接的复用,降低了系统建立新连接的开销,同时也加速了用户的访问速度。下面介绍连接池中连接的分配、释放策略。

slide46

连接池的分配、释放策略对于有效复用连接非常重要,我们采用的方法是一个很有名的设计模式:Reference Counting(引用记数)。该模式在复用资源方面应用的非常广泛,把该方法运用到对于连接的分配释放上,为每一个数据库连接,保留一个引用记数,用来记录该连接的使用者的个数。具体的实现方法是:

slide48

当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就删除该连接,并判断当前连接池内总的连接数是否小于minConn(最小连接数),若小于就将连接池充满;如果没超过就将该连接标记为开放状态,可供再次复用。可以看出正是这套策略保证了数据库连接的有效复用,避免频繁地建立、释放连接所带来的系统资源开销。当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就删除该连接,并判断当前连接池内总的连接数是否小于minConn(最小连接数),若小于就将连接池充满;如果没超过就将该连接标记为开放状态,可供再次复用。可以看出正是这套策略保证了数据库连接的有效复用,避免频繁地建立、释放连接所带来的系统资源开销。

slide49

⑶ 连接池的配置

数据库连接池中到底要放置多少个连接,才能使系统的性能更佳,用minConn和maxConn来限制。minConn是当应用启动的时候连接池所创建的连接数,如果过大启动将变慢,但是启动后响应更快;如果过小启动加快,但是最初使用的用户将因为连接池中没有足够的连接不可避免的延缓了执行速度。因此应该在开发的过程中设定较小minConn,而在实际应用的中设定较大minConn。maxConn是连接池中的最大连接数,可以通过反复试验来确定此饱和点。为此在连接池类ConnectionPool中加入两个方法getActiveSize()和getOpenSize(),ActiveSize 表示某一时间有多少连接正被使用,OpenSize表示连接池中有多少连接被打开,反映了连接池使用的峰值。将这两个值在日志信息中反应出来, minConn的值应该小于平均ActiveSize,而maxConn的值应该在activeSize和OpenSize之间。

slide50

⑷ 连接池的关键技术

① 事务处理

 前面讨论的是关于使用数据库连接进行普通的数据库访问。对于事务处理,情况就变得比较复杂。因为事务本身要求原则性的保证,此时就要求对于数据库的操作符合"All-All-Nothing"原则,即要么全部完成,要么什么都不做。如果简单的采用上述的连接复用的策略,就会发生问题,因为没有办法控制属于同一个事务的多个数据库操作方法的动作,可能这些数据库操作是在多个连接上进行的,并且这些连接可能被其他非事务方法复用。Connection本身具有提供了对于事务的支持,可以通过设置Connection的AutoCommit属性为false,显式的调用 commit或rollback方法来实现。但是要安全、高效的进行连接复用,就必须提供相应的事务支持机制。方法是:采用显式的事务支撑方法,每一个事务独占一个连接。这种方法可以大大降低对于事务处理的复杂性,并且又不会妨碍连接的复用。

slide52

② 并发

  为了使连接管理服务有更大的通用性,我们必须要考虑到多线程环境,即并发问题。在一个多线程的环境下,必须要保证连接管理自身数据的一致性和连接内部数据的一致性,在这方面Java提供很好的支持(synchronized关键字),这样就很容易使连接管理成为线程安全的。

slide53

③ 多数据库服务器

  在实际应用中,应用程序常常需要访问多个不同的数据库。如何通过同一个连接池访问不同的数据库,是应用程序需要解决的一个核心问题

⑸ 连接池应用的实现

一个完整的连接池应用包括三个部分:DBConnectionPool类,负责从连接池获取(或创建)连接、将连接返回给连接池、系统关闭时关闭所有连接释放所有资源;DBConnectionManager类,负责装载和注册JDBC驱动、根据属性文件中定义的属性创建DBConnectionPool、跟踪应用程序对连接池的引用等;应用程序对连接池的使用。

slide54

本文实现的数据库连接池包括一个管理类DBConnectionManager,负责提供与多个连接池对象(DBConnectionPool类)之间的接口。每一个连接池对象管理一组封装过的JDBC连接对象Conn,封装过的JDBC连接对象Conn可以被任意数量的Model层的组件共享。

  类Conn 的设计很简单,如下所示:

Class Conn {

Private java. sgl .Connection con; //数据库连接对象

Public Boolean inUse ; //是否被使用

Public long lastAccess; //最近一次释放该连接的时间

Public int useCount; // 被使用次数

}

slide55

 下面是实现连接池的主要代码:

// 初始化数据库连接池

public static synchronized void FastInitPool()

throws Exception {

try { Class.forName(driver);

for (int i=0; i<size; i++) {

Connection con = createConnection();

if (con!=null) addConnection(con);

} } }

slide56

// 向连接池对象中添加数据库连接

private static void addConnection(Connection con) {

if (pool=null||pool1=null) {

pool=new Vector(size);

pool1=new Vector(size); }

pool.addElement(con);

pool1.addElement("false"); }

// 获取数据库连接

public static synchronized Connection getConn()

throws Exception {

Connection conn = null;

try { if (driver = null)

FastInitPool();

slide57

// 获得一个可用的(空闲的)连接

.for (int i = 0; i < pool.size(); i++) {

conn = (Connection)pool.elementAt(i);

if (pool1.elementAt(i)=="false") {

pool1.set(i,"true");

//System.out.println("从连接池中获取第"+(i+1)+"个空闲连接");

return conn;

}

}

slide58

//如果没有可用连接,且已有连接数小于最大连接数限制,则创建并增加一个新连接到连接池

conn = createConnection();

pool.addElement(conn);

pool1.addElement("true");

// System.out.println(" 所有连接都在使用,在连接池中再创建一个新连接");

}

catch (Exception e) {

System.err.println(e.getMessage());

throw new Exception(e.getMessage());

}

slide59

return conn; //返回一个有效的新连接

}

public Connection getConnection(String strDriver, String strUrl, String strUserName, String strPassWord)

throws SQLException{

try{ Class.forName(strDriver);

conn = DriverManager.getConnection(strUrl, strUserName, strPassWord); }

return conn; }

slide60

作  业

①:利用JDBC驱动程序完成对MySQL数据库中数据表的查询、修改、删除、插入等操作(表内容自己定义)

②:编写JSP页面利用JDBC驱动程序完成对SQL SERVER数据库中存储过程的调用

教学总结:

slide61

上机实验十:JDBC与SQL语句、存储过程的应用(2课时)上机实验十:JDBC与SQL语句、存储过程的应用(2课时)

一、实验目的及要求

1.掌握JDBC连接不同数据库的连接字符串

2.掌握JSP页面中如何存取SQLserver中存储过程中的输入参数、输出参数、输入输出参数

3.通过上机实验掌握JDBC数据类型及类型转换

二、实验环境

Myeclipse、Tomcat、JDK

slide62

三、实验内容

1. 上机完成教案中示例

2.上机调试如下代码,其中存储过程根据代码在相应数据库中自行定义。

<%@ page contentType="text/html;charset=GBK" %>

<%@ page import="java.sql.*" %>

<html>

<head>

</head>

<% try {

String url="jdbc:odbc:xsfsql" ;

Connection conn;

java.sql.CallableStatement st;

slide63

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

conn=DriverManager.getConnection(url,"sa","");

out.println("<p>Join Success</p>");

st=conn.prepareCall(" {call queryxm1(?) }");

st.setString(1,"xxyyzz");

//st.setString(2,"");

//st.setDouble(3,0);

ResultSet rs=st.executeQuery();

slide64

while (rs.next())

out.println(rs.getString("xm"));

} catch (Exception ex ){

ex.printStackTrace();

}

%></html>

3.对SQL server数据库中的存储过程分别设置intput、output、inout参数并在JSP页面中用相关方法获取其值并显示在浏览器中。

四、实验步骤

slide65

五、实验思考

1.在将WEB项目发布到Internet上租用服务器上时,建立数据库连接是用JDBC的哪种驱动程序比较合适?

2.在设计数据库连接池的时候该注意哪些方面?

ad