Step By Step(Java JDBC篇)
2011-09-14 21:01
274 查看
JDBC是Sun公司发布的数据库连接API组件,使开发人员可以通过这个API接口连接到多种数据库,如Oracle、MySQL等,并使用SQL语句完成数据库的查询和更新等操作。JDBC主要分为两层,第一层为Java的接口层,主要面向Java的应用程序开发者,它定义了操作数据库的各种功能的接口,第二层为数据库驱动层,为数据库供应商提供了注册其数据库产品驱动程序的接口,两者之间是通过驱动管理器来负责协调和管理的。由于JDBC为所有支持的数据库提供了统一的API接口,因此在实际的开发中,如果软件产品被要求同时支持多种数据库平台,其间主要的差异将来自于不同数据库产品在特殊SQL语句方面的差异,至于调用接口方面,如果没有使用极为依赖数据库平台的接口API,那么该部分程序代码将不用作出任何改变。以下我们将通过示例代码的方式逐步了解JDBC中提供的API接口。
1. 创建与数据库的连接:
在使用Oracle的jdbc驱动之前需要先将Oracle提供的ojdbc14.jar添加到你的工程中,该文件一般位于"C:\oracle\product\10.2.0\db_1\jdbc\lib",以下示例用于验证你的驱动是否正常安装:
在确认驱动正常工作之后,尝试连接你的Oracle数据库,见下例:
2. 创建和删除表。
3. 插入新的数据。
4. 数据执行查询语句。
该示例代码主要包括两种常用的查询方式,一种是常量方式,另一种是动态绑定查询条件参数的形式。两者的主要差异为:
通过动态绑定条件的方式进行查询,该方式的查询比直接使用常量的方式性能要高,因为对于很多数据库服务器而言,在多次执行时,都会将下面这种动态绑定参数的sql语句视为同一语句,因此在被提交后,数据库服务器会通过该语句的hash值从解析好的cache中去查找,如果找到匹配的,就不会在对当前语句进行解析,只是带进不同的参数,继续使用原有的语法树直接执行就可以了。相反对于上面那种常量写法,数据库服务器每次都会将其视为新的语句,因此每次都会执行解析过程,从而降低了执行效率,增添了数据库cpu的开销。
5. 通过结果集的方式获取Columns的Metadata信息。
6. 通过可滚动结果集逆向访问行记录。
需要注意的是,如果结果集中数据量比较大,而可滚动结果集的底层实现方式是将当前查询的所有记录都传到客户端本地,然后再自行维护结果集的游标信息。因为在原生的数据库C接口API中,如Oracle的OCI和MySQL的API中,均不支持此种方式的结果集,而且结果集中的数据也是分批批量下载到本地的,而这种可滚动结果集的实现则是完全交由上层来完成的。
7. 向数据库的表中插入日期型和Timestamp类型的数据,同时执行查询并取出刚刚插入的日期和Timestamp类型的数据。
8. 获取Table或者View这些数据库内部对象的Metadata信息。通过该种方式获取数据库对象的metadata信息,比直接通过SQL语句查询数据库服务器内置的数据字典表或试图要更加容易在多种数据库之间迁移。还有一种方法用于判断表或试图是否存在,同时还能获取他们所包含columns的信息。执行"select * from " + tableName + " where 1=0" 该查询语句将不会有任何数据返回,但是对于判定该表是否存在,以及各个columns的metadata信息已经是足够了。
9. 批量数据插入。
当有大量数据需要被同时插入的时候,如果使用批量插入的方式可以大大提高插入的效率。其中效率提高主要源于一次性的批量插入减少了大量的网络IO,与此同时,数据库服务器在一次收到多条记录插入时,可以执行更好的优化处理。特别对于实时性比较高,数据量也很大的系统,使用批量插入确实可以给系统带来明显的改善。
10. 执行存储过程:
11. 获取存储过程的Metadata:
12. 插入和查询BLOB类型的二进制数据。
1. 创建与数据库的连接:
在使用Oracle的jdbc驱动之前需要先将Oracle提供的ojdbc14.jar添加到你的工程中,该文件一般位于"C:\oracle\product\10.2.0\db_1\jdbc\lib",以下示例用于验证你的驱动是否正常安装:
publicstaticvoid main(String[] args) { System.out.println("TestJDBCDriverInstallation_Oracle begin"); try { String className ="oracle.jdbc.driver.OracleDriver"; Class<?> driverObject = Class.forName(className); System.out.println("driverObject="+ driverObject); System.out.println("your installation of JDBC Driver OK."); } catch (Exception e) { // your installation of JDBC Driver Failed System.out.println("Failed: JDBC Driver Error: "+ e.getMessage()); } System.out.println("TestJDBCDriverInstallation_Oracle end."); }
在确认驱动正常工作之后,尝试连接你的Oracle数据库,见下例:
//以非sysdba的身份登录 publicstaticvoid main(String[] args) throws Exception { Class.forName("oracle.jdbc.driver.OracleDriver"); /* @//192.168.1.101:1526/OraHome * @//host_ip:port/SID */ Connection conn = DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome","scott","123456"); Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery("select * from user_tables"); while (rset.next()) System.out.println(rset.getString(1)); stmt.close(); } //以sysdba的身份登录 publicstaticvoid main(String[] args) throws Exception { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); Connection conn = DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome",conProps); //创建statement,并通过它执行sql查询。 Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery("select * from user_tables"); while (rset.next()) { System.out.println(rset.getString(1)); } stmt.close(); }
2. 创建和删除表。
publicstaticvoid main(String[] args) throws ClassNotFoundException{ Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); Connection conn =null; Statement statement =null; try { conn = DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); statement = conn.createStatement(); String sql ="CREATE TABLE books (id NUMBER(11), title VARCHAR2(64))"; statement.execute(sql); } catch (SQLException e) { e.printStackTrace(); } finally { try { //为了方便程序的测试,创建后建议删除测试数据。 String sql ="drop table books"; statement.execute(sql); statment.close(); conn.close(); } catch (SQLException e) { } } }
3. 插入新的数据。
publicclass MyTest { privatestaticfinal String EMPLOYEE_TABLE ="create table MyEmployees3 ( " +" id INT PRIMARY KEY, firstName VARCHAR(20), lastName VARCHAR(20), " +" title VARCHAR(20), salary INT "+")"; privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; Statement stmt =null; try { conn = getConnection(); stmt = conn.createStatement(); stmt.executeUpdate(EMPLOYEE_TABLE); stmt.executeUpdate("insert into MyEmployees3(id, firstName) values(100, 'A')"); stmt.executeUpdate("insert into MyEmployees3(id, firstName) values(200, 'B')"); System.out.println("main(): table created."); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { try { stmt.execute("drop table MyEmployees3"); stmt.close(); conn.close(); } catch (Exception e) { } } } }
4. 数据执行查询语句。
该示例代码主要包括两种常用的查询方式,一种是常量方式,另一种是动态绑定查询条件参数的形式。两者的主要差异为:
通过动态绑定条件的方式进行查询,该方式的查询比直接使用常量的方式性能要高,因为对于很多数据库服务器而言,在多次执行时,都会将下面这种动态绑定参数的sql语句视为同一语句,因此在被提交后,数据库服务器会通过该语句的hash值从解析好的cache中去查找,如果找到匹配的,就不会在对当前语句进行解析,只是带进不同的参数,继续使用原有的语法树直接执行就可以了。相反对于上面那种常量写法,数据库服务器每次都会将其视为新的语句,因此每次都会执行解析过程,从而降低了执行效率,增添了数据库cpu的开销。
publicclass MyTest { privatestaticfinal String EMPLOYEE_TABLE ="create table MyEmployees3 ( " +" id INT PRIMARY KEY, firstName VARCHAR(20), lastName VARCHAR(20), " +" title VARCHAR(20), salary INT "+")"; privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; Statement stmt =null; PreparedStatement pstmt =null; ResultSet rs =null; try { conn = getConnection(); stmt = conn.createStatement(); stmt.executeUpdate(EMPLOYEE_TABLE); stmt.executeUpdate("insert into MyEmployees3(id, firstName) values(100, 'A')"); stmt.executeUpdate("insert into MyEmployees3(id, firstName) values(200, 'B')"); String sql ="select id, firstName,lastName from MyEmployees3"; rs = stmt.executeQuery(sql); // extract data from the ResultSet while (rs.next()) { int id = rs.getInt(1); String firstname = rs.getString(2); String lastname = rs.getString(3); System.out.println("id = "+ id); System.out.println("firstname = "+ firstname); if (lastname ==null) System.out.println("the lastname is null."); System.out.println("lastname = "+ lastname); System.out.println("---------------"); } rs.close(); //动态绑定查询参数 sql ="select id from MyEmployees3 where firstName = ?"; pstmt = conn.prepareStatement(sql); ParameterMetaData paramMetaData = pstmt.getParameterMetaData(); if (paramMetaData ==null) { System.out.println("db does NOT support ParameterMetaData"); } else { System.out.println("db supports ParameterMetaData"); int paramCount = paramMetaData.getParameterCount(); System.out.println("paramCount="+ paramCount); } pstmt.setString(1, "A"); rs = pstmt.executeQuery(); while (rs.next()) { int id = rs.getInt(1); System.out.println("id = "+ id); System.out.println("---------------"); } } catch (Exception e) { e.printStackTrace(); } finally { try { stmt.execute("drop table MyEmployees3"); rs.close(); pstmt.close(); stmt.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
5. 通过结果集的方式获取Columns的Metadata信息。
publicclass MyTest { privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } privatestaticvoid getColumnNames(ResultSet rs) throws SQLException { ResultSetMetaData rsMetaData = rs.getMetaData(); int numberOfColumns = rsMetaData.getColumnCount(); for (int i =1; i <= numberOfColumns; ++i) { String columnName = rsMetaData.getColumnName(i); System.out.println("column = "+ columnName); } } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; Statement stmt =null; ResultSet rs =null; try { conn = getConnection(); String query ="select * from user_tables"; stmt = conn.createStatement(); rs = stmt.executeQuery(query); getColumnNames(rs); } catch (Exception e) { e.printStackTrace(); } finally { // release database resources try { rs.close(); stmt.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
6. 通过可滚动结果集逆向访问行记录。
需要注意的是,如果结果集中数据量比较大,而可滚动结果集的底层实现方式是将当前查询的所有记录都传到客户端本地,然后再自行维护结果集的游标信息。因为在原生的数据库C接口API中,如Oracle的OCI和MySQL的API中,均不支持此种方式的结果集,而且结果集中的数据也是分批批量下载到本地的,而这种可滚动结果集的实现则是完全交由上层来完成的。
publicclass MyTest { privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; Statement stmt =null; ResultSet rs =null; try { conn = getConnection(); stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rs = stmt.executeQuery("SELECT * from user_tables"); System.out.println("Got results:"); // position rs after the last row rs.afterLast(); while (rs.previous()) { String tablename = rs.getString("table_name"); System.out.println("Table_Name = "+ tablename); } System.out.println("Done."); } catch (Exception e) { e.printStackTrace(); } finally { if (conn !=null) { try { conn.close(); } catch (SQLException e) { } } } } }
7. 向数据库的表中插入日期型和Timestamp类型的数据,同时执行查询并取出刚刚插入的日期和Timestamp类型的数据。
publicclass MyTest { privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; Statement stmt =null; PreparedStatement pstmt =null; ResultSet rs =null; try { // 1. 创建带有各种日期类型的表。 String createTable ="CREATE TABLE TestDates (" +"id VARCHAR2(10)," +"date_column DATE,"+"time_column DATE," +"timestamp_column TIMESTAMP(6))"; conn = getConnection(); stmt = conn.createStatement(); stmt.execute(createTable); stmt.close(); // 2. 插入各种日期类型的数据 String insertRecord ="insert into TestDates(id, date_column, " +"time_column, timestamp_column) values(?, ?, ?, ?)"; pstmt = conn.prepareStatement(insertRecord); pstmt.setString(1, "001"); java.util.Date date =new java.util.Date(); long t = date.getTime(); java.sql.Date sqlDate =new java.sql.Date(t); java.sql.Time sqlTime =new java.sql.Time(t); java.sql.Timestamp sqlTimestamp =new java.sql.Timestamp(t); System.out.println("Begin inserting."); System.out.println("sqlDate = "+ sqlDate); System.out.println("sqlTime = "+ sqlTime); System.out.println("sqlTimestamp = "+ sqlTimestamp); pstmt.setDate(2, sqlDate); pstmt.setTime(3, sqlTime); pstmt.setTimestamp(4, sqlTimestamp); pstmt.executeUpdate(); System.out.println("End inserting."); pstmt.close(); // 3. 查询日期型数据 String getRecord ="select date_column, time_column, " +"timestamp_column from TestDates where id = ?"; pstmt = conn.prepareStatement(getRecord); pstmt.setString(1, "001"); System.out.println("Begin selecting."); rs = pstmt.executeQuery(); while (rs.next()) { java.sql.Date dbSqlDate = rs.getDate(1); java.sql.Time dbSqlTime = rs.getTime(2); java.sql.Timestamp dbSqlTimestamp = rs.getTimestamp(3); System.out.println("dbSqlDate = "+ dbSqlDate); System.out.println("dbSqlTime = "+ dbSqlTime); System.out.println("dbSqlTimestamp = "+ dbSqlTimestamp); } System.out.println("End selecting."); //4. 删除表 String dropTable ="drop table TestDates"; stmt = conn.createStatement(); stmt.execute(dropTable); } catch (Exception e) { e.printStackTrace(); } finally { try { rs.close(); pstmt.close(); conn.close(); } catch (SQLException e) { } } } }
8. 获取Table或者View这些数据库内部对象的Metadata信息。通过该种方式获取数据库对象的metadata信息,比直接通过SQL语句查询数据库服务器内置的数据字典表或试图要更加容易在多种数据库之间迁移。还有一种方法用于判断表或试图是否存在,同时还能获取他们所包含columns的信息。执行"select * from " + tableName + " where 1=0" 该查询语句将不会有任何数据返回,但是对于判定该表是否存在,以及各个columns的metadata信息已经是足够了。
//获取当前schema包含的table和view的metadata数据。 publicclass MyTest { privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; ResultSet rs =null; try { conn = getConnection(); DatabaseMetaData dbmd = conn.getMetaData(); String[] types = { "VIEW" ,"TABLE"}; //getTables(String catalog, String schemaPattern, // String tableNamePattern, String types[]) //其中前三个参数如果为null,表示不进行任何过滤。 rs = dbmd.getTables(null, null, "%", types); while (rs.next()) { String tableName = rs.getString(3); System.out.println("Tablename = "+ tableName); String tableCatalog = rs.getString(1); System.out.println("TableCatalog = "+ tableCatalog); String tableSchema = rs.getString(2); System.out.println("TableSchema = "+ tableSchema); } } catch (Exception e) { e.printStackTrace(); } finally { try { rs.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } //获取当前db下所有schema,及其包含的数据库对象的metadata。 publicclass MyTest { privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; try { conn = getConnection(); DatabaseMetaData dmd = conn.getMetaData(); //1. 获取当前数据库的所有schema信息 ResultSet rs1 = dmd.getSchemas(); while (rs1.next()) { String ss = rs1.getString(1); //2. 根据得到schema名字作为过滤条件,来获取其包含的objects的metadata ResultSet rs2 = dmd.getTables(null, ss, "%", null); while (rs2.next()) { System.out.println(rs2.getString(3) +""+ rs2.getString(4)); } rs2.close(); } rs1.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
9. 批量数据插入。
当有大量数据需要被同时插入的时候,如果使用批量插入的方式可以大大提高插入的效率。其中效率提高主要源于一次性的批量插入减少了大量的网络IO,与此同时,数据库服务器在一次收到多条记录插入时,可以执行更好的优化处理。特别对于实时性比较高,数据量也很大的系统,使用批量插入确实可以给系统带来明显的改善。
publicclass MyTest { privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; try { conn = getConnection(); String strCreateTable ="create table product (name varchar2(20),birthyear int)"; conn.createStatement().execute(strCreateTable); DatabaseMetaData dmd = conn.getMetaData(); //1. 确定该数据库服务器是否支持批量插入 if (dmd.supportsBatchUpdates()) { //2. 将自动commit关闭,最后提交时刻的决定交由手工来完成 conn.setAutoCommit(false); String sql ="INSERT into product VALUES(?,?)"; //3. 准备批量插入的数据 PreparedStatement prest = conn.prepareStatement(sql); prest.setString(1, "A"); prest.setInt(2, 2002); prest.addBatch(); prest.setString(1, "B"); prest.setInt(2, 1998); prest.addBatch(); prest.setString(1, "C"); prest.setInt(2, 1980); prest.addBatch(); prest.setString(1, "D"); prest.setInt(2, 1975); prest.addBatch(); //4. 执行批量插入 int count[] = prest.executeBatch(); //5. 手动提交批量插入的数据到数据库服务器。 conn.commit(); } } catch (Exception e) { e.printStackTrace(); } finally { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } //通过Statement方式批量插入 publicclass MyTest { privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; try { conn = getConnection(); String strCreateTable ="create table product1 (id int,name varchar2(20))"; conn.createStatement().execute(strCreateTable); DatabaseMetaData dmd = conn.getMetaData(); if (dmd.supportsBatchUpdates()) { conn.setAutoCommit(false); Statement stmt = conn.createStatement(); stmt.addBatch("INSERT INTO product1(id, name) VALUES(1, 'A')"); stmt.addBatch("INSERT INTO product1(id, name) VALUES(2, 'B')"); stmt.addBatch("INSERT INTO product1(id, name) VALUES(3, 'C')"); stmt.addBatch("DELETE FROM product1"); // 4. 执行批量插入 int[] updateCounts = stmt.executeBatch(); // 5. 手动提交批量插入的数据到数据库服务器。 conn.commit(); } } catch (Exception e) { e.printStackTrace(); } finally { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
10. 执行存储过程:
publicclass MyTest { privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; Statement stmt =null; try { conn = getConnection(); //1. 创建函数或存储过程 stmt = conn.createStatement(); String function ="CREATE OR REPLACE FUNCTION myfuncinout(" + "x IN VARCHAR,y OUT VARCHAR) RETURN VARCHAR IS " +"BEGIN y:= x||'outvalue'; RETURN 'a returned string'; END;"; stmt.executeUpdate(function); //2. 准备调用存储过程 CallableStatement cs = conn.prepareCall("{? = call myfuncinout(?,?)}"); //3. 注册返回值输出参数 cs.registerOutParameter(1, Types.VARCHAR); cs.registerOutParameter(3, Types.VARCHAR); //4. 设置输入参数 cs.setString(2, "hello"); //5. 执行存储过程 cs.execute(); String retValue = cs.getString(1); // return value String outParam = cs.getString(3); // IN/OUT parameter System.out.println("Return value = "+ retValue); System.out.println("Out value = "+ outParam); } catch (Exception e) { e.printStackTrace(); } finally { try { stmt.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
11. 获取存储过程的Metadata:
publicclass MyTest { privatestatic Connection getConnection() throws SQLException, ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) throws ClassNotFoundException { Connection conn =null; ResultSet rs =null; try { conn = getConnection(); DatabaseMetaData meta = conn.getMetaData(); //存储过程使用以下函数获取。 rs = meta.getProcedures(null, null, "%"); while (rs.next()) { String spName = rs.getString("PROCEDURE_NAME"); int spType = rs.getInt("PROCEDURE_TYPE"); System.out.println("Stored Procedure Name: "+ spName); if (spType == DatabaseMetaData.procedureReturnsResult) { System.out.println("procedure Returns Result"); } elseif (spType == DatabaseMetaData.procedureNoResult) { System.out.println("procedure No Result"); } else { System.out.println("procedure Result unknown"); } } } catch (Exception e) { e.printStackTrace(); } finally { try { rs.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
12. 插入和查询BLOB类型的二进制数据。
publicclass MyTest { privatestatic Connection getConnection() throws ClassNotFoundException, SQLException { Class.forName("oracle.jdbc.driver.OracleDriver"); Properties conProps =new Properties(); conProps.put("user", "sys"); conProps.put("password", "helloworld"); conProps.put("internal_logon", "sysdba"); return DriverManager.getConnection( "jdbc:oracle:thin:@//192.168.1.101:1526/OraHome", conProps); } publicstaticvoid main(String[] args) { Connection conn =null; try { conn = getConnection(); conn.setAutoCommit(false); // 创建带有blob字段的表 String strSQL ="CREATE TABLE Test(name VARCHAR2(20),content BLOB)"; Statement stmt = conn.createStatement(); stmt.execute(strSQL); //1. 插入一个空的BLOB oracle.sql.BLOB blob =null; String insertSQL ="insert into Test(name,content) values(?,empty_blob())"; PreparedStatement pstmt = conn.prepareStatement(insertSQL); pstmt.setString(1, "hello"); pstmt.executeUpdate(); pstmt.close(); //2. 取出刚刚插入的带有空blob数据的记录。 //注意:对于示例中的Oracle数据库,此次查询需要使用for update关键字, //以保证在查询的同时锁定当前的记录。 String selectSQL ="select content from Test where name= ? for update"; pstmt = conn.prepareStatement(selectSQL); pstmt.setString(1, "hello"); ResultSet rset = pstmt.executeQuery(); //3. 得到该BLOB字段数据操作的游标。 if (rset.next()) blob = (oracle.sql.BLOB) rset.getBlob(1); //4. 开始准备读入待插入的测试文件的数据。 String fileName ="D:/Test.rar"; File f =new File(fileName); FileInputStream fin =new FileInputStream(f); System.out.println("file size = "+ fin.available()); String updateSQL ="update Test set content=? where name=?"; pstmt = conn.prepareStatement(updateSQL); OutputStream out = blob.getBinaryOutputStream(); byte[] data =newbyte[(int) fin.available()]; //从文件将数据读入到内存,之后在写入blob的底层流 fin.read(data); out.write(data); fin.close(); out.close(); //5. 更新准备的二进制数据到数据库。 pstmt.setBlob(1, blob); pstmt.setString(2, "hello"); pstmt.executeUpdate(); pstmt.close(); conn.commit(); String strDrop ="drop table Test"; stmt = conn.createStatement(); stmt.execute(strDrop); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { System.err.println(e.getMessage()); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
相关文章推荐
- Step by Step,用JAVA做一个FLAPPYBIRD游戏(四)
- Step by Step - Turning Ruby Files into Java Classes(中英文对照版)
- Spark客户端Java程序开发Step By Step
- Step By Step(Java 常用对象篇<一>)
- Step by Step,用JAVA做一个FLAPPYBIRD游戏(六)
- Step By Step(Java 2D图形篇<三>)
- Step By Step(Java 输入输出篇)
- Step By Step(Java 国际化篇)
- Java step by step (1) : simple Spring IoC container
- 搭建Java开发环境(Step by step)
- Step by Step,用JAVA做一个FLAPPYBIRD游戏(五)
- Step By Step(Java 2D图形篇<一>)
- Windows系统配置Java Web开发环境Step by Step
- Java初学札记step by step(一)
- Step By Step(Java 2D图形篇<四>)
- Java回调理解 (step by step)
- Step By Step(Java 系列的目录)
- Step-by-Step搭建Linux下的java开发环境
- Step By Step(Java 2D图形篇<一>)
- Step by Step,用JAVA做一个FLAPPYBIRD游戏(一)