JDBC(2)

  • JDBC接口

接口

应用场景

Statement

当在运行时使用静态 SQL 语句时(Statement接口不能接受的参数)

PrepareStatement

当计划多次使用 SQL 语句时(PreparedStatement 接口接收在运行时输入参数)

CallableStatement

当要访问数据库中的存储过程时(CallableStatement对象的接口还可以接受运行时输入参数)

 

  • Statement接口

1、boolean execute(String SQL)    

       如果 ResultSet 对象可以被检索返回布尔值 true,否则返回 false。使用这个方法来执行 SQL DDL 语句,或当需要使用真正的动态 SQL

2、int executeUpdate(String SQL)    

        用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQLDDL(数据定义语言)语句。返回值是一个整数,指示受影响的行数(即更新计数)

3、ResultSet executeQuery(String SQL)    

       返回 ResultSet 对象。用于产生单个结果集的语句,例如 SELECT 语句

 

  • PrepareStatement接口

PreparedStatement 接口扩展了 Statement 接口,有利于高效地执行多次使用的 SQL 语句

import java.sql.*;

public class JdbcTest {

   // JDBC 驱动器的名称和数据库地址

   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; 

   static final String DB_URL = "jdbc:mysql://localhost/EXAMPLE";

   static final String USER = "root";

   static final String PASS = "";

   public static void main(String[] args) {

       Connection conn = null;

       PreparedStatement stmt = null;

       try{

           //注册 JDBC 驱动器

           Class.forName("com.mysql.jdbc.Driver");

           //打开连接

           System.out.println("Connecting to database...");

           conn = DriverManager.getConnection(DB_URL,USER,PASS);

           //执行查询

           System.out.println("Creating statement...");

           //这里我们要更改一个同学的年龄,参数待定

           String sql = "UPDATE Students set age=? WHERE id=?";

           stmt = conn.prepareStatement(sql);

           //将值绑定到参数,参数从左至右序号为1,2...

           stmt.setInt(1, 22);  // 绑定 age 的值(序号为1)

           stmt.setInt(2, 1); // 绑定 ID 的值

           // 更新 ID 为1的同学的年龄

           int rows = stmt.executeUpdate();

           System.out.println("被影响的行数 : " + rows );

           // 查询所有记录,并显示.

           sql = "SELECT id, name, age FROM Students";

           ResultSet rs = stmt.executeQuery(sql);

           //处理结果集

           while(rs.next()){

               //检索

               int id  = rs.getInt("id");

               int age = rs.getInt("age");

               String name = rs.getString("name");

               //显示

               System.out.print("ID: " + id);

               System.out.print(", Age: " + age);

               System.out.print(", Name: " + name);

               System.out.println();

           }

           //清理

           rs.close();

           stmt.close();

           conn.close();

       }catch(SQLException se){

           se.printStackTrace();

       }catch(Exception e){

           e.printStackTrace();

       }finally{

           try{

               if(stmt!=null)

                   stmt.close();

           }catch(SQLException se2){

           }

    try{

         if(conn!=null)

                 conn.close();

      }catch(SQLException se){

              se.printStackTrace();

          }

       }

           System.out.println("Goodbye!");

   }

}

 

  • CallableStatement接口

CallableStatement 对象为所有的 DBMS 提供了一种以标准形式调用存储过程的方法。存储过程储存在数据库中。对储存过程的调用是 CallableStatement 对象所含的内容。三种类型的参数有:IN,OUT和INOUT。

CallableStatement cstmt = null;

try {

   String SQL = "{call getEXAMPLEName (?, ?)}";

   cstmt = conn.prepareCall (SQL);

   . . .

}

catch (SQLException e) {

   . . .

}

finally {

   cstmt.close();

}
  • ResultSet结果集

结果集通常是通过执行查询数据库的语句生成,表示数据库查询结果的数据表。ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。光标可以方便我们对结果集进行遍历。默认的 ResultSet 对象不可更新,仅有一个向前移动的光标。因此,只能迭代它一次,并且只能按从第一行到最后一行的顺序进行。

 

ResultSet接口的方法可分为三类:

1、导航方法:用于移动光标

2、获取方法:用于查看当前行的光标所指向的列中的数据

3、更新方法:用于更新当前行的列中的数据

 

JDBC 提供下列连接方法来创建所需的ResultSet语句:

createStatement(int RSType, int RSConcurrency);

prepareStatement(String SQL, int RSType, int RSConcurrency);

prepareCall(String sql, int RSType, int RSConcurrency);

RSType 表示 ResultSet 对象的类型,RSConcurrency 是 ResultSet 常量,用于指定一个结果集是否为只读或可更新。

ResultSet 的类型,如果不指定 ResultSet 类型,将自动获得一个是 TYPE_FORWARD_ONLY。

类型(RSType)

描述

ResultSet.TYPE_FORWARD_ONLY

游标只能向前移动的结果集

ResultSet.TYPE_SCROLL_INSENTITIVE

游标可以向前和向后滚动,但不及时更新,就是如果数据库里的数据修改过,

并不在ResultSet中反应出来

ResultSet.TYPE_SCROLL_SENTITIVE

游标可以向前和向后滚动,并及时跟踪数据库的更新,以便更改ResultSet中的数据

 

并发(RSConcurrency)

描述

ResultSet.CONCUR_READ_ONLY

创建结果集只读。默认

ResultSet.CONCUR_READ_UPDATABLE

创建一个可更新的结果集

比如初始化一个 Statement 对象来创建一个双向、可更新的ResultSet对象:

try {

         Statement stmt = conn.createStatement(

                                 ResultSet.TYPE_SCROLL_INSENSITIVE,

                                 ResultSet.CONCUR_UPDATABLE);

      }

      catch(Exception ex) {

         ....

      }

      finally {

         ....

      }

 

  • 导航方法(用于光标的移动)

ResultSet接口中以下方法涉及游标的移动:

实例代码:

import java.sql.*;

public class JdbcTest {

   // JDBC 驱动器名称 和数据库地址

   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";

   //数据库的名称为 EXAMPLE

   static final String DB_URL = "jdbc:mysql://localhost/EXAMPLE";

   // 数据库用户和密码

   static final String USER = "root";

   static final String PASS = "";

   public static void main(String[] args) {

       Connection conn = null;

       Statement stmt = null;

       try{

           //注册JDBC 驱动程序

           Class.forName("com.mysql.jdbc.Driver");

           //打开连接

           System.out.println("Connecting to database...");

           conn = DriverManager.getConnection(DB_URL,USER,PASS);

           System.out.println("Creating statement...");

           //创建所需的ResultSet,双向,只读

           stmt = conn.createStatement(

                           ResultSet.TYPE_SCROLL_INSENSITIVE,

                           ResultSet.CONCUR_READ_ONLY);

           String sql;

           sql = "SELECT id, name, age FROM Students";

           ResultSet rs = stmt.executeQuery(sql);

           // 将光标移到最后一行

           System.out.println("Moving cursor to the last...");

           rs.last();

           //处理结果集

           System.out.println("Displaying record...");

           int id  = rs.getInt("id");

           int age = rs.getInt("age");

           String name = rs.getString("name");

           //显示

           System.out.print("ID: " + id);

           System.out.print(", Age: " + age);

           System.out.print(", Name: " + name);

           System.out.println();

           // 将光标移到第一行

           System.out.println("Moving cursor to the first row...");

           rs.first();

           System.out.println("Displaying record...");

           id  = rs.getInt("id");

           age = rs.getInt("age");

           name = rs.getString("name");

           //显示

           System.out.print("ID: " + id);

           System.out.print(", Age: " + age);

           System.out.print(", Name: " + name);

           //将光标移至下一行

           System.out.println("Moving cursor to the next row...");

           rs.next();

           System.out.println("Displaying record...");

           id  = rs.getInt("id");

           age = rs.getInt("age");

           name = rs.getString("name");

           // 显示

           System.out.print("ID: " + id);

           System.out.print(", Age: " + age);

           System.out.print(", Name: " + name);

           rs.close();

           stmt.close();

           conn.close();

       }catch(SQLException se){

           se.printStackTrace();

       }catch(Exception e){

           e.printStackTrace();

       }finally{

           try{

               if(stmt!=null)

                   stmt.close();

           }catch(SQLException se2){

           }

           try{

               if(conn!=null)

                   conn.close();

           }catch(SQLException se){

               se.printStackTrace();

           }

       }

       System.out.println("Goodbye!");

   }

}

 

  • 获取方法(获取结果集的某填数据)

方法

说明

public int getInt(String columnName) throws SQLException

获取当前行中名为 ColumnName 列的值

public int getInt(int columnIndex) throws SQLException

获取当前行中指定列的索引的值。列索引从1开始,

意味着一个行的第一列是1,行的第二列是2。

getString等方式类似。

 

 

  • 更新方法

1、更新结果集

方法

说明

public void updateString(String columnName,String s) throws SQLException

修改当前行中名为 ColumnName 列的值为s

public void updateString (int columnIndex,String s)) throws SQLException

修改当前行中指定列中索引的值为s

updateDouble()等方式类似。

2、更新数据库(在更新结果集之后)

方法

说明

public void updateRow()

将当前行记录更新到数据库

public  void deleteRow()

从数据库删除当前行

public  void refreshRow()

 用数据库中的最近值刷新当前行

public  void cancelRowUpdates()

取消对 ResultSet 对象中的当前行所作的更新。此方法在调用更新方法之后,但在调用 updateRow 方法之前调用才可以回滚对行所作的更新。如果没有进行任何更新或者已经调用 updateRow 方法,则此方法无效

public  void insertRow()

将当前行记录插入到数据库

代码示例:

Statement stmt = conn.createStatement(

        ResultSet.TYPE_SCROLL_INSENSITIVE,

        ResultSet.CONCUR_UPDATABLE);

String sql = "SELECT id, name, age FROM Students";

ResultSet rs = stmt.executeQuery(sql);

//将光标移动到一个特殊的行,可以用来插入新行到结果集。当前光标位置被记住

rs.moveToInsertRow();

//结果集中插入新行

rs.updateInt("id",5);

rs.updateString("name","John");

rs.updateInt("age",21);

//将插入结果集的新行插入到数据库中

rs.insertRow();

//将光标返回到当前行(返回到moveToInsertRow() 方法中被记住的光标位置)

rs.moveToCurrentRow();

 

  • JDBC事务

默认情况下,JDBC连接是自动提交模式的,每条SQL语句执行完后自动提交到数据库。

事务是一条或者多条SQL语句作为一个逻辑单元,并且如果事务中任何语句执行失败,则整个事务失败。

自己管理和控制事务可以:

1、提高程序的运行性能

2、保持业务流程的完整性

3、采用分布式事务管理方式

 

事务的四大特性:(ACID)

1、原子性(Atomicity)

2、一致性(Consistency)

3、隔离性(Isolation)

4、持久性(Durability)

 

开启JDBC事务需要关闭自动提交:

Connection conn = null;

conn = DriverManager.getConnection(URL);

//关闭自动提交

conn.setAutoCommit(false);

事务的提交:

conn.commit();

事务的回滚:

conn.rollBack();

 

代码示例:

import java.sql.*;

public class JdbcTest {

   // JDBC 驱动器名称 和数据库地址

   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; 

   //数据库的名称为 EXAMPLE

   static final String DB_URL = "jdbc:mysql://localhost/EXAMPLE";

   //  数据库用户和密码

   static final String USER = "root";

   static final String PASS = ""; 

   public static void main(String[] args) {

       Connection conn = null;

       Statement stmt = null;

       try{

           //注册JDBC 驱动程序

           Class.forName("com.mysql.jdbc.Driver");

           //打开连接

           System.out.println("Connecting to database...");

           conn = DriverManager.getConnection(DB_URL,USER,PASS);

           conn.setAutoCommit(false); 

           //执行查询

           System.out.println("Creating statement...");

           stmt = conn.createStatement();

           //插入

           String sql = "INSERT INTO Students  " +

                    "VALUES (5, 20, 'Rose')";

           stmt.executeUpdate(sql);

           //查找

           sql = "SELECT id, name, age FROM Students";

           ResultSet rs = stmt.executeQuery(sql);

           //提交事务

           conn.commit();

           //得到和处理结果集

           while(rs.next()){

               //检索

               int id  = rs.getInt("id");

               int age = rs.getInt("age");

               String name = rs.getString("name");

               //显示

               System.out.print("ID: " + id);

               System.out.print(", Age: " + age);

               System.out.print(", Name: " + name);

               System.out.println();

           }

           //清理环境

           rs.close();

           stmt.close();

           conn.close();

       }catch(SQLException se){

           // JDBC 操作错误

           se.printStackTrace();

           // conn.rollback();

           try{

                 if(conn!=null)

                    conn.rollback();

              }catch(SQLException se2){

                 se2.printStackTrace();

              }

       }catch(Exception e){

           // Class.forName 错误

           e.printStackTrace();

       }finally{

           //这里一般用来关闭资源的

           try{

               if(stmt!=null)

                   stmt.close();

           }catch(SQLException se2){

           }

           try{

               if(conn!=null)

                   conn.close();

           }catch(SQLException se){

               se.printStackTrace();

           }

       }

       System.out.println("Goodbye!");

   }

}

 

  • JDBC批处理

       批量处理允许将相关的SQL语句分组到批处理中,并通过对数据库的一次调用来提交它们,一次执行完成与数据库之间的交互。

       不需要JDBC驱动程序来支持此功能。应该使用DatabaseMetaData.supportsBatchUpdates()方法来确定目标数据库是否支持批量更新处理。如果JDBC驱动程序支持此功能,该方法将返回true。

 

  • 使用Statement对象进行批处理

1、使用createStatement()方法创建一个Statement对象

2、设置使用自动提交为 false

3、添加任意多个SQL 语句到批量处理,使用addBatch()方法

4、使用executeBatch()方法,将返回一个整数数组,数组中的每个元素代表了各自的更新语句的更新计数

5、最后,提交使用commit()方法的所有更改
 

//创建 statement 对象

Statement stmt = conn.createStatement();

//关闭自动提交

conn.setAutoCommit(false);

//创建 SQL 语句

String SQL = "INSERT INTO Students (id, name, age) VALUES(6,'Mike', 21)";

//将 SQL 语句添加到批处理中

stmt.addBatch(SQL);

//创建更多的 SQL 语句

String SQL = "INSERT INTO Students (id, name, age) VALUES(7, 'Angle', 23)";

//将 SQL 语句添加到 批处理中

stmt.addBatch(SQL);

//创建整数数组记录更新情况

int[] count = stmt.executeBatch();

//提交更改

conn.commit()

 

  • 使用prepareStatement对象进行批处理
String SQL = "INSERT INTO Employees (id, name, age) VALUES(?, ?, ?)";

//创建 PrepareStatement 对象

PreparedStatemen pstmt = conn.prepareStatement(SQL);

//关闭自动连接

conn.setAutoCommit(false);

//绑定参数

pstmt.setInt( 1, 8 );

pstmt.setString( 2, "Cindy" );

pstmt.setInt( 3, 17 );

//添入批处理

pstmt.addBatch();

//绑定参数

pstmt.setInt( 1, 9 );

pstmt.setString( 2, "Jeff" );

pstmt.setInt( 3, 22 );

//添入批处理

pstmt.addBatch();

//创建数组记录更改

int[] count = pstmt.executeBatch();

//提交更改

conn.commit();

 

posted @ 2018-01-11 00:00  Rapleal  阅读(146)  评论(0编辑  收藏  举报