JDBC简析

JDBC


JDBC简介

常见的JDBC组件

DriverManager :这个类管理一系列数据库驱动程序。匹配连接使用通信子协议从 JAVA 应用程序中请求合适的数据库驱动程序。识别 JDBC 下某个子协议的第一驱动程序将被用于建立数据库连接。
Driver : 这个接口处理与数据库服务器的通信。你将很少直接与驱动程序互动。相反,你使用 DriverManager 中的对象,它管理此类型的对象。它也抽象与驱动程序对象工作相关的详细信息。
Connection : 此接口具有接触数据库的所有方法。该连接对象表示通信上下文,即,所有与数据库的通信仅通过这个连接对象进行。
Statement : 使用创建于这个接口的对象将 SQL 语句提交到数据库。除了执行存储过程以外,一些派生的接口也接受参数。
ResultSet : 在你使用语句对象执行 SQL 查询后,这些对象保存从数据获得的数据。它作为一个迭代器,让您可以通过它的数据来移动。
SQLException : 这个类处理发生在数据库应用程序的任何错误。

创建JDBC应用程序

  • 导入数据包:需要你导入含有需要进行数据库编程的 JDBC 类的包。大多数情况下,使用 import java.sql. 就足够了。
  • 注册 JDBC 驱动器:需要你初始化一个驱动器,以便于你打开一个与数据库的通信通道。
  • 打开连接:需要使用 DriverManager.getConnection() 方法创建一个 Connection 对象,它代表与数据库的物理连接。
  • 执行查询:需要使用类型声明的对象建立并提交一个 SQL 语句到数据库。
  • 提取结果数据:要求使用适当的 ResultSet.getXXX() 方法从结果集中检索数据。
  • 清理环境:依靠 JVM 的垃圾收集来关闭所有需要明确关闭的数据库资源。
//STEP 1. Import required packages 导入数据包
import java.sql.*;

public class FirstExample {
   // JDBC driver name and database URL
   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
   static final String DB_URL = "jdbc:mysql://localhost/EMP";

   //  Database credentials 
   static final String USER = "username";
   static final String PASS = "password";

   public static void main(String[] args) {
   Connection conn = null;
   Statement stmt = null;
   try{
      //STEP 2: Register JDBC driver 注册JDBC驱动器
      Class.forName("com.mysql.jdbc.Driver");

      //STEP 3: Open a connection 打开连接
      System.out.println("Connecting to database...");
      conn = DriverManager.getConnection(DB_URL,USER,PASS);

      //STEP 4: Execute a query 执行查询
      System.out.println("Creating statement...");
      stmt = conn.createStatement();
      String sql;
      sql = "SELECT id, first, last, age FROM Employees";
      ResultSet rs = stmt.executeQuery(sql);

      //STEP 5: Extract data from result set 提取结果数据
      while(rs.next()){
         //Retrieve by column name
         int id  = rs.getInt("id");
         int age = rs.getInt("age");
         String first = rs.getString("first");
         String last = rs.getString("last");

         //Display values
         System.out.print("ID: " + id);
         System.out.print(", Age: " + age);
         System.out.print(", First: " + first);
         System.out.println(", Last: " + last);
      }
      //STEP 6: Clean-up environment 清理环境
      rs.close();
      stmt.close();
      conn.close();
   }catch(SQLException se){
      //Handle errors for JDBC
      se.printStackTrace();
   }catch(Exception e){
      //Handle errors for Class.forName
      e.printStackTrace();
   }finally{
      //finally block used to close resources
      try{
         if(stmt!=null)
            stmt.close();
      }catch(SQLException se2){
      }// nothing we can do
      try{
         if(conn!=null)
            conn.close();
      }catch(SQLException se){
         se.printStackTrace();
      }//end finally try
   }//end try
   System.out.println("Goodbye!");
}//end main
}//end FirstExample
注册JDBC驱动程序

方法一 - Class.forName()

注册一个驱动程序中最常用的方法是使用 Java 的Class.forName() 方法来动态加载驱动程序的类文件到内存中,它会自动将其注册。这种方法更优越一些,因为它允许你对驱动程序的注册信息进行配置,便于移植。

你可以使用 getInstance() 方法来解决不兼容的 JVM,但你必须编写如下所示的两个额外的异常

try {
   Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
}
catch(ClassNotFoundException ex) {
   System.out.println("Error: unable to load driver class!");
   System.exit(1);
catch(IllegalAccessException ex) {
   System.out.println("Error: access problem while loading!");
   System.exit(2);
catch(InstantiationException ex) {
   System.out.println("Error: unable to instantiate driver!");
   System.exit(3);
}

方法二 - DriverManager.registerDriver()

注册一个驱动程序的第二种方法是使用静态 staticDriverManager.registerDriver() 方法。
如果你使用的是不兼容 JVM 的非 JDK,比如微软提供的,你必须使用 registerDriver() 方法。

数据库URL制定

当你加载了驱动程序之后,你可以通过 DriverManager.getConnection() 方法建立一个连接

  • getConnection(String url)
  • getConnection(String url, Properties prop)
  • getConnection(String url, String user, String password)

在这里,每个格式需要一个数据库 URL ,数据库 URL 是指向数据库的地址。

RDBMJDBC驱动程序名称URL格式
MySQLcom.mysql.jdbc.Driverjdbc:mysql://hostname/ databaseName
ORACLEoracle.jdbc.driver.OracleDriverjdbc:oracle:thin:@hostname:port Number:databaseName
DB2COM.ibm.db2.jdbc.net.DB2Driverjdbc:db2:hostname:port Number/databaseName
Sybasecom.sybase.jdbc.SybDriverjdbc:sybase:Tds:hostname: port Number/databaseName
创建连接对象

前两种不赘述了。
使用数据库URL和Properties对象

    DriverManager.getConnection(String url, Properties info);

Properties 对象保存了一组关键数值。它通过调用 getConnection() 方法,将驱动程序属性传递给驱动程序。

String URL = "jdbc:oracle:thin:@amrood:1521:EMP";
Properties info = new Properties( );
info.put( "user", "username" );
info.put( "password", "password" );

Connection conn = DriverManager.getConnection(URL, info);
关闭数据库连接

JDBC语法

JDBC Statement对象

一旦我们获得了数据库的连接,我们就可以和数据库进行交互。JDBC 的 StatementCallableStatementPreparedStatement 接口定义的方法和属性,可以让你发送 SQL 命令或 PL/SQL 命令到数据库,并从你的数据库接收数据。

接口推荐使用
Statement可以正常访问数据库,适用于运行静态 SQL 语句。 Statement 接口不接受参数。
PreparedStatement计划多次使用 SQL 语句, PreparedStatement 接口运行时接受输入的参数。
CallableStatement适用于当你要访问数据库存储过程的时候, CallableStatement 接口运行时也接受输入的参数。
创建Statement对象

在你准备使用 Statement 对象执行 SQL 语句之前,你需要使用 Connection 对象的 createStatement() 方法创建一个

当你创建了一个 Statement 对象之后,你可以用它的三个执行方法的任一方法来执行 SQL 语句。

  • boolean execute(String SQL) : 如果 ResultSet 对象可以被检索,则返回的布尔值为 true ,否则返回 false 。当你需要使用真正的动态 SQL 时,可以使用这个方法来执行 SQL DDL 语句。
  • int executeUpdate(String SQL) : 返回执行 SQL 语句影响的行的数目。使用该方法来执行 SQL 语句,是希望得到一些受影响的行的数目,例如,INSERT,UPDATE 或 DELETE 语句。
  • ResultSet executeQuery(String SQL) : 返回一个 ResultSet 对象。当你希望得到一个结果集时使用该方法,就像你使用一个 SELECT 语句。
创建PreparedStatement对象
PreparedStatement pstmt = null;
try {
   String SQL = "Update Employees SET age = ? WHERE id = ?";
   pstmt = conn.prepareStatement(SQL);
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   . . .
}

JDBC 中所有的参数都被用 ? 符号表示,这是已知的参数标记。在执行 SQL 语句之前,你必须赋予每一个参数确切的数值。
setXXX() 方法将值绑定到参数,其中 XXX 表示你希望绑定到输入参数的 Java 数据类型。如果你忘了赋予值,你将收到一个 SQLException。
每个参数标记映射它的序号位置。第一标记表示位置 1 ,下一个位置为 2 等等。这种方法不同于 Java 数组索引,它是从 0 开始的。

所有的 Statement对象 的方法都与数据库交互,(a) execute(),(b) executeQuery(),及 (c) executeUpdate() 也能被 PreparedStatement 对象引用。然而,这些方法被 SQL 语句修改后是可以输入参数的。

创建CallableStatement对象

假如你需要执行以下的 Oracle 存储过程

CREATE OR REPLACE PROCEDURE getEmpName 
   (EMP_ID IN NUMBER, EMP_FIRST OUT VARCHAR) AS
BEGIN
   SELECT first INTO EMP_FIRST
   FROM Employees
   WHERE ID = EMP_ID;
END;

注意:上面的存储过程已经写入到 Oracle 数据库中,但我们正在使用 MySQL 数据库,那么我们可以在 MySQL 的 EMP 数据库中创建相同的存储过程。

DELIMITER $$

DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $$
CREATE PROCEDURE `EMP`.`getEmpName` 
   (IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255))
BEGIN
   SELECT first INTO EMP_FIRST
   FROM Employees
   WHERE ID = EMP_ID;
END $$

DELIMITER ;

三种类型的参数有:IN,OUT 和 INOUT。PreparedStatement 对象只使用 IN 参数。CallableStatement 对象可以使用所有的三个参数。

参数描述
IN在 SQL 语句创建的时候该参数是未知的。你可以用 setXXX() 方法将值绑定到IN参数中。
OUT该参数由 SQL 语句的返回值提供。你可以用 getXXX() 方法获取 OUT 参数的值。
INOUT该参数同时提供输入输出的值。你可以用 setXXX() 方法将值绑定参数,并且用 getXXX() 方法获取值。

下面的代码片段展示了基于存储过程如何使用 Connection.prepareCall() 方法来实例化 CallableStatement 对象。

SQL 的 String 变量使用参数占位符表示存储过程。
使用 CallableStatement 对象就像使用 PreparedStatement 对象。你必须在执行该语句之前将值绑定到所有的参数,否则你将收到一个 SQL 异常。
如果你有 IN 参数,只要使用适用于 PreparedStatement 对象相同的规则和技巧;使用 setXXX() 方法绑定对应的 Java 数据类型。
当你使用 OUT 和 INOUT 参数时,你就必须使用额外的 CallableStatement 方法 - registerOutParameter()。 registerOutParameter() 方法绑定 JDBC 数据类型,该数据是存储过程返回的值。
一旦你调用存储过程,你可以用适当的 getXXX() 方法来获取 OUT 参数的值。这个方法将检索到的 SQL 类型映射成 Java 数据类型。


JDBC 结果集

结果集

SQL 语句从数据库查询中获取数据,并将数据返回到结果集中。SELECT 语句是一种标准的方法,它从一个数据库中选择行记录,并显示在一个结果集中。java.sql.ResultSet 接口表示一个数据库查询的结果集。
一个 ResultSet 对象控制一个光标指向当前行的结果集。
ResultSet 接口的方法可细分为三类
- 导航方法:用于移动光标
- 获取方法:用于查看的当前行被光标说指向的列中的数据
- 更新方法:用于更新当前行的列中的数据。这些更新也会更新数据库中的数据

JDBC 提供了连接方法通过下列创建语句来生成你所需的 ResultSet 对象:
- createStatement(int RSType, int RSConcurrency);
- prepareStatement(String SQL, int RSType, int RSConcurrency);
- prepareCall(String sql, int RSType, int RSConcurrency);

第一个参数表示 ResultSet 对象的类型,第二个参数是两个 ResultSet 常量之一,该常量用于判断该结果集是只读的还是可修改的。

ResultSet的类型

可能的 RSType 如下所示。如果你不指定 ResultSet 类型,将自动获得的值是 TYPE_FORWARD_ONLY。

类型描述
ResultSet.TYPE_FORWARD_ONLY光标只能在结果集中向前移动。
ResultSet.TYPE_SCROLL_INSENSITIVE光标可以向前和向后移动。当结果集创建后,其他人对数据库的操作不会影响结果集的数据。
ResultSet.TYPE_SCROLL_SENSITIVE.光标可以向前和向后移动。当结果集创建后,其他人对数据库的操作会影响结果集的数据。
ResultSet 的并发性

RSConcurrency 的值如下所示,如果你不指定并发类型,将自动获得的值是 CONCUR_READ_ONLY。

并发性描述
ResultSet.CONCUR_READ_ONLY创建一个只读结果集,这是默认的值。
ResultSet.CONCUR_UPDATABLE创建一个可修改的结果集。
导航结果集

在 ResultSet 接口中包括如下几种方法涉及移动光标

S.N.方法&描述
1public void beforeFirst() throws SQLException
将光标移动到第一行之前。
2public void afterLast() throws SQLException
将光标移动到最后一行之后。
3public boolean first() throws SQLException
将光标移动到第一行。
4public void last() throws SQLException
将光标移动到最后一行。
5public boolean absolute(int row) throws
将光标移动到指定的第 row 行。
6public boolean relative(int row) throws
将光标移动到当前指向的位置往前或往后第 row 行的位置。
7public boolean previous() throws SQLException
将光标移动到上一行,如果超过结果集的范围则返回 false。
8public boolean next() throws SQLException
将光标移动到下一行,如果是结果集的最后一行则返回 false。
9public int getRow() throws SQLException
返回当前光标指向的行数的值。
10public void moveToInsertRow() throws SQLException
将光标移动到结果集中指定的行,可以在数据库中插入新的一行。当前光标位置将被记住。
11public void moveToCurrentRow() throws SQLException
如果光标处于插入行,则将光标返回到当前行,其他情况下,这个方法不执行任何操作。
查看结果集

ResultSet接口中含有几十种从当前行获取数据的方法。
每个可能的数据类型都有一个 get 方法,并且每个 get 方法有两个版本
- 一个需要列名
- 一个需要列的索引

更新结果集

ResultSet 接口包含了一系列的更新方法,该方法用于更新结果集中的数据。
用 get 方法可以有两个更新方法来更新任一数据类型
- 一个需要列名
- 一个需要列的索引

更新结果集中的行将改变当前行的列中的 ResultSet 对象,而不是基础数据库中的数据。要更新数据库中一行的数据,你需要调用以下的任一方法

S.N.方法&描述
1public void updateRow()
通过更新数据库中相对应的行来更新当前行。
2public void deleteRow()
从数据库中删除当前行。
3public void refreshRow()
在结果集中刷新数据,以反映数据库中最新的数据变化。
4public void cancelRowUpdates()
取消对当前行的任何修改。
5public void insertRow()
在数据库中插入一行。本方法只有在光标指向插入行的时候才能被调用。

JDBC 数据类型

JDBC 3.0 增强了对 BLOB,CLOB,ARRAY 和 REF 数据类型的支持。 ResultSet 对象现在有 UPDATEBLOB(),updateCLOB(), updateArray(),和 updateRef()方法,通过这些方法你可以直接操作服务器上的相应数据。
你能用 setXXX()方法和 updateXXX()方法将 Java 类型转换为特定的 JDBC 数据类型。你能用 setObject()方法和 updateObject()方法将绝大部分的 Java 类型映射到 JDBC 数据类型。
ResultSet 对象为任一数据类型提供相应的 getXXX()方法,该方法可以获取任一数据类型的列值。上述任一方法的使用需要列名或它的顺序位置。

SQLJDBC/JavasetXXXgetXXX
VARCHARjava.lang.StringsetStringgetString
CHARjava.lang.StringsetStringgetString
LONGVARCHARjava.lang.StringsetStringgetString
BITbooleansetBooleangetBoolean
NUMERICjava.math.BigDecimalsetBigDecimalgetBigDecimal
TINYINTbytesetBytegetByte
SMALLINTshortsetShortgetShort
INTEGERintsetIntgetInt
BIGINTlongsetLonggetLong
REALfloatsetFloatgetFloat
FLOATfloatsetFloatgetFloat
DOUBLEdoublesetDoublegetDouble
VARBINARYbyte[ ]setBytesgetBytes
BINARYbyte[ ]setBytesgetBytes
DATEjava.sql.DatesetDategetDate
TIMEjava.sql.TimesetTimegetTime
TIMESTAMPjava.sql.TimestampsetTimestampgetTimestamp
CLOBjava.sql.ClobsetClobgetClob
BLOBjava.sql.BlobsetBlobgetBlob
ARRAYjava.sql.ArraysetARRAYgetARRAY
REFjava.sql.RefSetRefgetRef
STRUCTjava.sql.StructSetStructgetStruct
日期和时间数据类型

java.sql.Date 类映射 SQL DATE 类型,java.sql.Time 类和 java.sql.Timestamp 类也分别映射 SQL TIME 数据类型和 SQL TIMESTAMP 数据类型。

处理NULL值

SQL 使用 NULL 值和 Java 使用 null 是不同的概念。那么,你可以使用三种策略来处理 Java 中的 SQL NULL 值

  • 避免使用返回原始数据类型的 getXXX()方法。
  • 使用包装类的基本数据类型,并使用 ResultSet 对象的 wasNull()方法来测试收到 getXXX()方法返回的值是否为 null,如果是 null,该包装类变量则被设置为 null。
  • 使用原始数据类型和 ResultSet 对象的 wasNull()方法来测试通过 getXXX()方法返回的值,如果是 null,则原始变量应设置为可接受的值来代表 NULL。

JDBC 事务

事务

如果你的 JDBC 连接是处于自动提交模式下,该模式为默认模式,那么每句 SQL 语句都是在其完成时提交到数据库。
对简单的应用程序来说这种模式相当好,但有三个原因你可能想关闭自动提交模式,并管理你自己的事务

  • 为了提高性能
  • 为了保持业务流程的完整性
  • 使用分布式事务

你可以通过事务在任意时间来控制以及更改应用到数据库。它把单个 SQL 语句或一组 SQL 语句作为一个逻辑单元,如果其中任一语句失败,则整个事务失败。
若要启用手动事务模式来代替 JDBC 驱动程序默认使用的自动提交模式的话,使用 Connection 对象的的 setAutoCommit()方法。如果传递一个布尔值 false 到 setAutoCommit()方法,你就关闭自动提交模式。你也可以传递一个布尔值 true 将其再次打开。
例如,如果有一个名为 conn 的 Connection 对象,以下的代码将关闭自动提交模式

conn.setAutoCommit(false);
提交和回滚

当你完成了你的修改,并且要提交你的修改,可以在 connection 对象里调用 commit()方法,如下所示

conn.commit();

另外,用名为 conn 的连接回滚数据到数据库,使用如下所示的代码

conn.rollback();
使用还原点

新的 JDBC 3.0 还原点接口提供了额外的事务控制。大部分现代的数据库管理系统的环境都支持设定还原点,例如 Oracle 的 PL/SQL。
当你在事务中设置一个还原点来定义一个逻辑回滚点。如果在一个还原点之后发生错误,那么可以使用 rollback 方法来撤消所有的修改或在该还原点之后所做的修改。
Connection 对象有两个新的方法来管理还原点

  • setSavepoint(String savepointName): 定义了一个新的还原点。它也返回一个 Savepoint 对象。
  • releaseSavepoint(Savepoint savepointName): 删除一个还原点。请注意,它需要一个作为参数的 Savepoint 对象。这个对象通常是由 setSavepoint() 方法生成的一个还原点。

JDBC 异常

异常

异常处理可以允许你处理一个异常情况,例如可控方式的程序定义错误。
当异常情况发生时,将抛出一个异常。抛出这个词意味着当前执行的程序停止,控制器被重定向到最近的适用的 catch 子句。如果没有适用的 catch 子句存在,那么程序执行被终止。
JDBC 的异常处理是非常类似于 Java 的异常处理,但对于 JDBC,最常见的异常是 java.sql.SQLException

SQLException 方法

SQLException 异常在驱动程序和数据库中都可能出现。当出现这个异常时,SQLException 类型的对象将被传递到 catch 子句。
传递的 SQLException 对象具有以下的方法,以下的方法可用于检索该异常的额外信息

方法描述
getErrorCode( )获取与异常关联的错误号。
getMessage( )获取 JDBC 驱动程序的错误信息,该错误是由驱动程序处理的,或者在数据库错误中获取 Oracl 错误号和错误信息。
getSQLState( )获取 XOPEN SQLstate 字符串。对于 JDBC 驱动程序错误,使用该方法不能返回有用的信息。对于数据库错误,返回第五位的 XOPEN SQLstate 代码。该方法可以返回 null。
getNextException( )获取异常链的下一个 Exception 对象。
printStackTrace( )打印当前异常或者抛出,其回溯到标准的流错误。
printStackTrace(PrintStream s)打印该抛出,其回溯到你指定的打印流。
printStackTrace(PrintWriter w)打印该抛出,其回溯到你指定的打印写入。

JDBC 批处理

批处理

批处理是指你将关联的 SQL 语句组合成一个批处理,并将他们当成一个调用提交给数据库。
当你一次发送多个 SQL 语句到数据库时,可以减少通信的资源消耗,从而提高了性能。
- JDBC 驱动程序不一定支持该功能。你可以使用 DatabaseMetaData.supportsBatchUpdates() 方法来确定目标数据库是否支持批处理更新。如果你的JDBC驱动程序支持此功能,则该方法返回值为 true。
- Statement,PreparedStatement 和 CallableStatement 的 addBatch() 方法用于添加单个语句到批处理。
- executeBatch() 方法用于启动执行所有组合在一起的语句。
- executeBatch() 方法返回一个整数数组,数组中的每个元素代表了各自的更新语句的更新数目。
- 正如你可以添加语句到批处理中,你也可以用 clearBatch() 方法删除它们。此方法删除所有用 addBatch() 方法添加的语句。但是,你不能有选择性地选择要删除的语句。

批处理和Statement对象

使用 Statement 对象来使用批处理所需要的典型步骤如下所示
- 使用 createStatement() 方法创建一个 Statement 对象。
- 使用 setAutoCommit() 方法将自动提交设为 false。
- 被创建的 Statement 对象可以使用 addBatch() 方法来添加你想要的所有SQL语句。
- 被创建的 Statement 对象可以用 executeBatch() 将所有的 SQL 语句执行。
- 最后,使用 commit() 方法提交所有的更改。

批处理和PrepareStatement对象

使用 prepareStatement 对象来使用批处理需要的典型步骤如下所示
- 使用占位符创建 SQL 语句。
- 使用任一 prepareStatement() 方法创建 prepareStatement 对象。
- 使用 setAutoCommit() 方法将自动提交设为 false。
- 被创建的 Statement 对象可以使用 addBatch() 方法来添加你想要的所有 SQL 语句。
- 被创建的 Statement 对象可以用 executeBatch() 将所有的 SQL 语句执行。
- 最后,使用 commit() 方法提交所有的更改。


JDBC 的SQL转义语法

转义语法使能够让你通过使用标准的 JDBC 方法和属性,来灵活的使用数据库的某些特定功能,而该特定功能对你来说本来是不可用的。
常用的 SQL 转义语法格式如下所示

{keyword 'parameters'}
d, t, ts关键字

它们能帮助确定日期,时间和时间戳的文字。众所周知,没有两个数据库管理系统的时间和日期的表现方式是相同的。该转义语法告诉驱动程序以目标数据库的格式来呈现日期或时间。例如

{d 'yyyy-mm-dd'}

下面是一个说明如何在表中插入日期的简单例子-

//Create a Statement object
stmt = conn.createStatement();
//Insert data ==> ID, First Name, Last Name, DOB
String sql="INSERT INTO STUDENTS VALUES" +
             "(100,'Zara','Ali', {d '2001-12-16'})";

stmt.executeUpdate(sql);

同样的,你可以使用以下两种语法之一,无论是 t 或 ts

{t 'hh:mm:ss'}
{ts 'yyyy-mm-dd hh:mm:ss'}
escape关键字

该关键字在 LIKE 子句中使用,来定义转义字符。当使用 SQL 通配符%,来匹配零个或多个字符时,该关键字就非常有用。例如

String sql = "SELECT symbol FROM MathSymbols
              WHERE symbol LIKE '\%' {escape '\'}";
stmt.execute(sql);

如果你使用反斜杠字符(\)作为转义字符,你必须在 Java 字符串里使用两个反斜杠字符,因为反斜杠也是一个 Java 转义字符。

fn关键字

该关键字代表在数据库管理系统中使用标量函数。例如,你可以使用 SQL 的 length 函数来计算字符串的长度

{fn length('Hello World')}

这将返回11,也就是字符串’Hello World’的长度。

call关键字

该关键字是用来调用存储过程的。例如,对于一个需要一个 IN 参数的存储过程,使用以下语法

{call my_procedure(?)};

对于需要一个 IN 参数并返回一个 OUT 参数的存储过程,使用下面的语法

{? = call my_procedure(?)};
oj关键字

该关键字用来表示外部连接,其语法如下所示

{oj outer-join}

其中 outer - join = 表 { LEFT | RIGHT | FULL } OUTER JOIN {表| outer - join }的搜索条件。例如

String sql = "SELECT Employees 
              FROM {oj ThisTable RIGHT
              OUTER JOIN ThatTable on id = '100'}";
stmt.execute(sql);

JDBC 流数据

PreparedStatement 对象必须具备使用输入和输出流来提供参数数据的能力。这使你能够将整个文件存储到数据库列中,这样数据库就能存储大型数据,例如 CLOB 和 BLOB 数据类型。

用于流数据有下列几种方法
- setAsciiStream(): 该方法是用来提供较大的 ASCII 值。
- setCharacterStream(): 该方法是用来提供较大的 UNICODE 值。
- setBinaryStream(): 该方法是用来提供较大的二进制值。

示例

上传一个XML文件
将该 XML 文件和你要运行的示例保存在相同的目录的。
这个示例将创建一个数据库表 XML_Data ,然后 XML_Data.xml 将被上传到该表中。
将下面的示例拷贝并粘帖到 JDBCExample.java 中,编译并运行它,如下所示

import java.sql.*;
import java.io.*;
import java.util.*;

public class JDBCExample {
   // JDBC driver name and database URL
   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
   static final String DB_URL = "jdbc:mysql://localhost/EMP";

   //  Database credentials
   static final String USER = "username";
   static final String PASS = "password";

   public static void main(String[] args) {
   Connection conn = null;
   PreparedStatement pstmt = null;
   Statement stmt = null;
   ResultSet rs = null;
   try{
      // Register JDBC driver
      Class.forName("com.mysql.jdbc.Driver");

      // Open a connection
      System.out.println("Connecting to database...");
      conn = DriverManager.getConnection(DB_URL,USER,PASS);

      //Create a Statement object and build table
      stmt = conn.createStatement();
      createXMLTable(stmt);

      //Open a FileInputStream
      File f = new File("XML_Data.xml");
      long fileLength = f.length();
      FileInputStream fis = new FileInputStream(f);

      //Create PreparedStatement and stream data
      String SQL = "INSERT INTO XML_Data VALUES (?,?)";
      pstmt = conn.prepareStatement(SQL);
      pstmt.setInt(1,100);
      pstmt.setAsciiStream(2,fis,(int)fileLength);
      pstmt.execute();

      //Close input stream
      fis.close();

      // Do a query to get the row
      SQL = "SELECT Data FROM XML_Data WHERE id=100";
      rs = stmt.executeQuery (SQL);
      // Get the first row
      if (rs.next ()){
         //Retrieve data from input stream
         InputStream xmlInputStream = rs.getAsciiStream (1);
         int c;
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         while (( c = xmlInputStream.read ()) != -1)
            bos.write(c);
         //Print results
         System.out.println(bos.toString());
      }
      // Clean-up environment
      rs.close();
      stmt.close();
      pstmt.close();
      conn.close();
   }catch(SQLException se){
      //Handle errors for JDBC
      se.printStackTrace();
   }catch(Exception e){
      //Handle errors for Class.forName
      e.printStackTrace();
   }finally{
      //finally block used to close resources
      try{
         if(stmt!=null)
            stmt.close();
      }catch(SQLException se2){
      }// nothing we can do
      try{
         if(pstmt!=null)
            pstmt.close();
      }catch(SQLException se2){
      }// nothing we can do
      try{
         if(conn!=null)
            conn.close();
      }catch(SQLException se){
         se.printStackTrace();
      }//end finally try
   }//end try
   System.out.println("Goodbye!");
}//end main

public static void createXMLTable(Statement stmt) 
   throws SQLException{
   System.out.println("Creating XML_Data table..." );
   //Create SQL Statement
   String streamingDataSql = "CREATE TABLE XML_Data " +
                             "(id INTEGER, Data LONG)";
   //Drop table first if it exists.
   try{
      stmt.executeUpdate("DROP TABLE XML_Data");
   }catch(SQLException se){
   }// do nothing
   //Build table.
   stmt.executeUpdate(streamingDataSql);
}//end createXMLTable
}//end JDBCExample
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值