JDBCTM 是一U用于执?SQL 语句?JavaTM APIQ有意思的是,JDBC 本n是个商标名而不是一个羃写字Q然而,JDBC常被认ؓ是代?“Java 数据库连?(Java Database Connectivity)”Q。它׃l用 Java ~程语言~写的类和接口组成。JDBC 为工?数据库开发h员提供了一个标准的 APIQ他们能够用纯Java API 来编写数据库应用E序。Java数据库连接(JDBCQ由一l用 Java ~程语言~写的类和接口组成。JDBC 为工?数据库开发h员提供了一个标准的 APIQ他们能够用纯Java API 来编写数据库应用E序。然而各个开发商的接口ƈ不完全相同,所以开发环境的变化会带来一定的配置变化?br />
JDBC 的用途是什么?单地_JDBC 可做三g事:与数据库建立q接Q发?SQL 语句Q处理结果?/p>
一、连接各U数据库方式速查?br />
下面|列了各U数据库使用JDBCq接的方式,可以作ؓ一个手册用?/p>
1、Oracle8/8i/9i数据库(thin模式Q?
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID
String user="test";
String password="test";
Connection conn= DriverManager.getConnection(url,user,password);
2、DB2数据?
Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
String url="jdbc:db2://localhost:5000/sample"; //sampleZ的数据库?
String user="admin";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);
3、Sql Server7.0/2000数据?
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb";
//mydb为数据库
String user="sa";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);
4、Sybase数据?
Class.forName("com.sybase.jdbc.SybDriver").newInstance();
String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDBZ的数据库?
Properties sysProps = System.getProperties();
SysProps.put("user","userid");
SysProps.put("password","user_password");
Connection conn= DriverManager.getConnection(url, SysProps);
5、Informix数据?
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url =
"jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
user=testuser;password=testpassword"; //myDB为数据库?
Connection conn= DriverManager.getConnection(url);
6、MySQL数据?
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
//myDB为数据库?
Connection conn= DriverManager.getConnection(url);
7、PostgreSQL数据?
Class.forName("org.postgresql.Driver").newInstance();
String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库?
String user="myuser";
String password="mypassword";
Connection conn= DriverManager.getConnection(url,user,password);
8、access数据库直q用ODBC?br />
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
Connection conn = DriverManager.getConnection(url,"","");
Statement stmtNew=conn.createStatement() ;
二、用JDBC来连接Oracle数据库时可以使用的一些技巧,q些技巧能够我们更好地发挥系l的性能和实现更多的功能Q系转蝲Q?/p>
1、在客户端Y件开发中使用Thin驱动E序
在开发Java软g斚wQOracle的数据库提供了四U类型的驱动E序Q二U用于应用Y件、applets、servlets{客L软gQ另外二U用于数据库中的Java存储q程{服务器端Y件。在客户机端软g的开发中Q我们可以选择OCI驱动E序或Thin驱动E序。OCI驱动E序利用Java本地化接口(JNIQ,通过Oracle客户端Y件与数据库进行通讯。Thin驱动E序是纯Java驱动E序Q它直接与数据库q行通讯。ؓ了获得最高的性能QOracle在客L软g的开发中使用OCI驱动E序Q这g是正的。但我徏议用Thin驱动E序Q因为通过多次试发现Q在通常情况下,Thin驱动E序的性能都超q了OCI驱动E序?/p>
2、关闭自动提交功能,提高pȝ性能
在第一ơ徏立与数据库的q接Ӟ在缺省情况下Q连接是在自动提交模式下的。ؓ了获得更好的性能Q可以通过调用带布值false参数的ConnectioncȝsetAutoCommit()Ҏ关闭自动提交功能Q如下所C:
conn.setAutoCommit(false);
值得注意的是Q一旦关闭了自动提交功能Q我们就需要通过调用Connectioncȝcommit()和rollback()Ҏ来h工的方式对事务进行管理?/p>
3、在动态SQL或有旉限制的命令中使用Statement对象
在执行SQL命oӞ我们有二U选择Q可以用PreparedStatement对象Q也可以使用Statement对象。无论多次C用同一个SQL命oQPreparedStatement都只对它解析和编译一ơ。当使用Statement对象Ӟ每次执行一个SQL命oӞ都会对它q行解析和编译。这可能会你认为,使用PreparedStatement对象比用Statement对象的速度更快。然而,我进行的试表明Q在客户端Y件中Q情况ƈ非如此。因此,在有旉限制的SQL操作中,除非成批地处理SQL命oQ我们应当考虑使用Statement对象?/p>
此外Q用Statement对象也得编写动态SQL命o更加单,因ؓ我们可以字W串q接在一P建立一个有效的SQL命o。因此,我认为,Statement对象可以使动态SQL命o的创建和执行变得更加单?/p>
4、利用helper函数对动态SQL命oq行格式?/p>
在创Z用Statement对象执行的动态SQL命oӞ我们需要处理一些格式化斚w的问题。例如,如果我们惛_Z个将名字O'Reilly插入表中的SQL命oQ则必须使用二个相连?#8220;''”h换O'Reilly中的“'”受完成这些工作的最好的Ҏ是创Z个完成替换操作的helperҎQ然后在q接字符串心服用公式表达一个SQL命oӞ使用创徏的helperҎ。与此类似的是,我们可以让helperҎ接受一个Date型的|然后让它输出ZOracle的to_date()函数的字W串表达式?/p>
5、利用PreparedStatement对象提高数据库的M效率
在用PreparedStatement对象执行SQL命oӞ命o被数据库q行解析和编译,然后被放到命令缓冲区。然后,每当执行同一个PreparedStatement对象Ӟ它就会被再解析一ơ,但不会被再次~译。在~冲Z可以发现预编译的命oQƈ且可以重C用。在有大量用L企业U应用Y件中Q经怼重复执行相同的SQL命oQ用PreparedStatement对象带来的编译次数的减少能够提高数据库的M性能。如果不是在客户端创建、预备、执行PreparedStatementd需要的旉长于StatementdQ我会徏议在除动态SQL命o之外的所有情况下使用PreparedStatement对象?/p>
6、在成批处理重复的插入或更新操作中用PreparedStatement对象
如果成批地处理插入和更新操作Q就能够显著地减它们所需要的旉。Oracle提供的Statement?CallableStatementq不真正地支持批处理Q只有PreparedStatement对象才真正地支持批处理。我们可以用addBatch()和executeBatch()Ҏ选择标准的JDBC批处理,或者通过利用PreparedStatement对象的setExecuteBatch()Ҏ和标准的executeUpdate()Ҏ选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制Q可以以如下所C的方式调用setExecuteBatch()Q?br />
PreparedStatement pstmt3D null;
try {
((OraclePreparedStatement)
pstmt).setExecuteBatch(30);
...
pstmt.executeUpdate();
}
调用setExecuteBatch()时指定的值是一个上限,当达到该值时Q就会自动地引发SQL命o执行Q标准的executeUpdate()Ҏ׃被作为批处理送到数据库中。我们可以通过调用PreparedStatementcȝsendBatch()Ҏ随时传输批处理Q务?/p>
7、用Oracle locatorҎ插入、更新大对象QLOBQ?/p>
Oracle的PreparedStatementcM完全支持BLOB和CLOB{大对象的处理,其是Thin驱动E序不支持利用PreparedStatement对象的setObject()和setBinaryStream()Ҏ讄BLOB的|也不支持利用setCharacterStream()Ҏ讄CLOB的倹{只有locator本n中的Ҏ才能够从数据库中获取LOBcd的倹{可以用PreparedStatement对象插入或更新LOBQ但需要用locator才能获取LOB的倹{由于存在这二个问题Q因此,我徏议用locator的方法来插入、更新或获取LOB的倹{?/p>
8、用SQL92语法调用存储q程
在调用存储过E时Q我们可以用SQL92或Oracle PL/SQLQ由于用Oracle PL/SQLq没有什么实际的好处Q而且会给以后l护你的应用E序的开发h员带来麻烦,因此Q我在调用存储过E时使用SQL92?/p>
9、用Object SQL对象模式{Ud数据库中
既然可以Oracle的数据库作ؓ一U面向对象的数据库来使用Q就可以考虑应用程序中的面向对象模式{到数据库中。目前的Ҏ是创建Java bean作ؓ伪装的数据库对象Q将它们的属性映到关系表中Q然后在q些bean中添加方法。尽这样作在Java中没有什么问题,但由于操作都是在数据库之外进行的Q因此其他访问数据库的应用Y件无法利用对象模式。如果利用Oracle的面向对象的技术,可以通过创徏一个新的数据库对象cd在数据库中模仿其数据和操作,然后使用JPublisher{工L成自qJava beancR如果用这U方式,不但Java应用E序可以使用应用软g的对象模式,其他需要共享你的应用中的数据和操作的应用Y件也可以使用应用软g中的对象模式?/p>
10、利用SQL完成数据库内的操?/p>
我要向大家介l的最重要的经验是充分利用SQL的面向集合的Ҏ来解x据库处理需求,而不是用Java{过E化的编E语a?/p>
如果~程人员要在一个表中查找许多行Q结果中的每个行都会查找其他表中的数据,最后,~程人员创徏了独立的UPDATE命o来成批地更新W一个表中的数据。与此类似的d可以通过在set子句中用多列子查询而在一个UPDATE命o中完成。当能够在单一的SQL命o中完成Q务,何必要让数据在网上流来流ȝQ我用户认真学习如何最大限度地发挥SQL的功能?
三、常用的JDBCcMҎ
1、DriverManagerc:
负责理JDBC驱动E序。用JDBC驱动E序之前Q必d驱动程序加载ƈ向DriverManager注册后才可以使用Q同时提供方法来建立与数据库的连接?
ҎQ?
A、Class.forName(String driver); //加蝲注册驱动E序
B、Static Connection getConnection(String url,String user,String password) throws SQLException;
//取得Ҏ据库的连?
C、Static Driver getDriver(String url) throws SQLExcetion;
//在已l向DriverManager注册的驱动程序中L一个能够打开url所指定的数据库的驱动程?
2、Connectionc?
负责l护JSP/JAVA数据库程序和数据库之间的联机。可以徏立三个非常有用的cd象?
ҎQ?
A、Statement createStatement() throws SQLException; //建立Statementcd?
Statement createStatement(int resultSetType,int resultSetConcurrency) throws SQLException;
// 建立Statementcd?
resultSetType?nbsp;
TYPE_FORWARD_ONLY l果集不可滚?nbsp;
TYPE_SCROLL_INSENSITIVE l果集可滚动Q不反映数据库的变化
TYPE_SCROLL_SENSITIVE l果集可滚动Q反映数据库的变?nbsp;
resultSetConcurrency?nbsp;
CONCUR_READ_ONLY 不能用结果集更新数据
CONCUR_UPDATABLE 能用l果集更新数?nbsp;
JDBC2.0中才支持滚动的结果集Q而且可以Ҏ据进行更?
B、DatabaseMetaData getMetaData() throws SQLException; //建立DatabaseMetaDatacd?
C、PreparedStatement prepareStatement(String sql) throws SQLException;
//建立PreparedStatementcd?
D、boolean getAutoCommit() throws SQLException //q回Connectioncd象的AutoCommit状?
E、void setAutoCommit(boolean autoCommit) throws SQLException
//讑֮Connectioncd象的AutoCommit状?
F、void commit() throws SQLException //定执行Ҏ据库新增、删除或修改记录的操?
G、void rollback() throws SQLException //取消执行Ҏ据库新增、删除或修改记录的操?
H、void close() throws SQLException //l束Connection对象Ҏ据库的联?
I、boolean isClosed() throws SQLException //试是否已经关闭Connectioncd象对数据库的联机
3、Statementc?
通过StatementcL提供的方法,可以利用标准的SQL命oQ对数据库直接新增、删除或修改操作
ҎQ?
A、ResultSet executeQuery(String sql) throws SQLException //使用SELECT命oҎ据库q行查询
B、int executeUpdate(String sql) throws SQLException
//使用INSERT\DELETE\UPDATEҎ据库q行新增、删除和修改操作?
C、void close() throws SQLException //l束Statementcd象对数据库的联机
4、PreparedStatementc?
PreparedStatementcdStatementcȝ不同之处在于PreparedStatementcd象会传入的SQL命o事先~好{待使用Q当有单一的SQL指o比多ơ执行时Q用PreparedStatementcM比StatementcL效率
ҎQ?
A、ResultSet executeQuery() throws SQLException //使用SELECT命oҎ据库q行查询
B、int executeUpdate() throws SQLException
//使用INSERT\DELETE\UPDATEҎ据库q行新增、删除和修改操作?
C、ResultSetMetaData getMetaData() throws SQLException
//取得ResultSetcd象有兛_D늚相关信息
D、void setInt(int parameterIndex,int x) throws SQLException
//讑֮整数cd数值给PreparedStatementcd象的IN参数
E、void setFloat(int parameterIndex,float x) throws SQLException
//讑֮点数类型数值给PreparedStatementcd象的IN参数
F、void setNull(int parameterIndex,int sqlType) throws SQLException
//讑֮NULLcd数值给PreparedStatementcd象的IN参数
G、void setString(int parameterIndex,String x) throws SQLException
//讑֮字符串类型数值给PreparedStatementcd象的IN参数
H、void setDate(int parameterIndex,Date x) throws SQLException
//讑֮日期cd数值给PreparedStatementcd象的IN参数
I、void setTime(int parameterIndex,Time x) throws SQLException
//讑֮旉cd数值给PreparedStatementcd象的IN参数
5、DatabaseMetaDatac?
DatabaseMetaDatacM存了数据库的所有特性,q且提供许多Ҏ来取得这些信息?
ҎQ?
A、String getDatabaseProductName() throws SQLException //取得数据库名U?
B、String getDatabaseProductVersion() throws SQLException //取得数据库版本代?
C、String getDriverName() throws SQLException //取得JDBC驱动E序的名U?
D、String getDriverVersion() throws SQLException //取得JDBC驱动E序的版本代?
E、String getURL() throws SQLException //取得q接数据库的JDBC URL
F、String getUserName() throws SQLException //取得d数据库的使用者帐?
6、ResultSetc?
负责存储查询数据库的l果。ƈ提供一pd的方法对数据库进行新增、删除和修改操作。也负责l护一个记录指针(CursorQ,记录指针指向数据表中的某个记录,通过适当的移动记录指针,可以随心所Ʋ的存取数据库,加强E序的效率?
ҎQ?
A、boolean absolute(int row) throws SQLException //Ud记录指针到指定的记录
B、void beforeFirst() throws SQLException //Ud记录指针到第一W记录之?
C、void afterLast() throws SQLException //Ud记录指针到最后一W记录之?
D、boolean first() throws SQLException //Ud记录指针到第一W记?
E、boolean last() throws SQLException //Ud记录指针到最后一W记?
F、boolean next() throws SQLException //Ud记录指针C一W记?
G、boolean previous() throws SQLException //Ud记录指针C一W记?
H、void deleteRow() throws SQLException //删除记录指针指向的记?
I、void moveToInsertRow() throws SQLException //Ud记录指针以新增一W记?
J、void moveToCurrentRow() throws SQLException //Ud记录指针到被记忆的记?
K、void insertRow() throws SQLException //新增一W记录到数据库中
L、void updateRow() throws SQLException //修改数据库中的一W记?
M、void updatecd(int columnIndex,cd x) throws SQLException //修改指定字段的?
N、int getcd(int columnIndex) throws SQLException //取得指定字段的?
O、ResultSetMetaData getMetaData() throws SQLException //取得ResultSetMetaDatacd?
7、ResultSetMetaDatac?
ResultSetMetaDatacd象保存了所有ResultSetcd象中关于字段的信息,提供许多Ҏ来取得这些信息?
ҎQ?
A、int getColumnCount() throws SQLException //取得ResultSetcd象的字段个数
B、int getColumnDisplaySize() throws SQLException //取得ResultSetcd象的字段长度
C、String getColumnName(int column) throws SQLException //取得ResultSetcd象的字段名称
D、String getColumnTypeName(int column) throws SQLException //取得ResultSetcd象的字段cd名称
E、String getTableName(int column) throws SQLException //取得ResultSetcd象的字段所属数据表的名U?
F、boolean isCaseSensitive(int column) throws SQLException //试ResultSetcd象的字段是否区分大小?
G、boolean isReadOnly(int column) throws SQLException //试ResultSetcd象的字段是否为只?
四、用存储过E?br />
单的老的JDBC通过CallableStatementcL持存储过E的调用。该cd际上是PreparedStatement的一个子cR假设我们有一个poets数据库。数据库中有一个设|诗人逝世q龄的存储过E。下面是对老酒鬼Dylan ThomasQold soak Dylan ThomasQ不指定是否有关典故、文化,h评指正。译注)q行调用的详l代码:

]]>