管理結果集(ResultSet)


可滾動,可更新的結果集(ResultSet):

 在早期,JAVA提供的ResultSet默認是不允許滾動的,因此為了實現ResultSet可滾動,需要在Connection創建Statement時傳入一個參數,resultSetType參數,同時還要出入另外一個參數resultSetConcurrency參數。

  ResultSet參數:控制ResultSet的類型,該參數取如下三值:

   ResultSet.TYPE_FORWARD_ONLY:該常量控制ResultSet記錄指針只能向前移動

   ResultSet.TYPE_SCROLL_INSENSITIVE:該常量控制ResultSet記錄指針可以自由移動(可滾動結果集),但底層數據的改變不會受ResultSet的內容

   ResultSet.TYPE_SCROLL_SENSITIVE:該常量控制ResultSet記錄指針可以自由移動(可滾動結果集),並且底層數據的改變會影響ResultSet的內容,即當程序獲取ResultSet后,操作了數據庫改變了內容,該ResultSet會對應更着變動。

  resultSetConcurrency參數:控制ResultSet的並發類型,該參數可以接收如下兩個值:

   ResultSet.CONCUR_READ_ONLY:該常量指示ResultSet是只讀的並發模式(默認)

   ResultSet.CONCUR_UPDATABLE: 該常量指示ResultSet是可更新的並發默認。

 但從Java5.0版本后,默認創建出來的Statement對象是允許滾動的,但該Statement對象是不允許可更新結果集。因此,在目前版本里,如果你創建Statement對象不用於更新數據內容,直接默認創建便可;但若要進行更新數據內容,則創建Statemet對象時,需要帶上上面兩個參數。(PreParedStatement以及CallableStatement也是一樣)

 要指出的是:如果要創建可更新的結果集,還需要下面兩個條件:

  1. ResultSet查詢的數據是來自於同一張表。

  2. ResultSet查詢的數據中有該表的主鍵列。

 滿足以上條件的ResultSet方可以進行更新操作,更新的操作如下:

  1. 修改當前行某列字段的值: ResultSet.updateXxx(int index,Xxx value);

  2. 提交修改數據並讓數據庫完成修改: ResultSet.updateRow();

 

下面是可滾動,可更新結果集的簡單示范:

public class JDBC {

    String driver;
      String url;
      String user;
      String password;

//可滾動,可更新的結果集
    public void resultSetTest(){
        ResultSet resultSet = null;
        String sql = "select * from tb_test";
        try{
//            Statement statement =conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
//            resultSet = statement.executeQuery("select * from tb_test");
            PreparedStatement preStatement = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
            resultSet = preStatement.executeQuery();

            resultSet.last();  //將ResultSet的記錄指針移動到最后一行
             //resultSet.getRow() 獲取記錄指針的當前行數,剛創建出來resultSet記錄指針指向0行,數據內容都是從1行開始
            int rowCount = resultSet.getRow();
            System.out.println("表一共有"+rowCount+"記錄");
            for(int i=rowCount;i>0;i--){
                resultSet.absolute(i); //將ResultSet的記錄指針移動到指定行數
                System.out.println("當前指針所在行數為:"+resultSet.getRow());
                System.out.println("第一次"+resultSet.getString(1)+","+resultSet.getString(2)+","+resultSet.getInt(3));
                resultSet.updateString(2, "HJJ_"+i);
                resultSet.updateRow();
                System.out.println("第二次"+resultSet.getString(1)+","+resultSet.getString(2)+","+resultSet.getInt(3));
            }
        }catch(Exception e){}
    }
    
    Connection conn = null;
    Statement statement = null;
    public JDBC(String paramFile){
        try{
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("Url");
            user = props.getProperty("user");
            password = props.getProperty("password");
            conn =DriverManager.getConnection(url,user,password);
            statement =conn.createStatement();
            
        }catch(Exception e){}
    }
    
    public static void main(String[] args) throws SQLException {
        JDBC jdbc_2 = new JDBC("mysql.properties");
        String table = "tb_test";
        
        jdbc_2.resultSetTest();
    }
}

 上述代碼中,可以使用Statement或者PrePareStatement來創建ResultSet對象。運行結果如下:

表一共有25記錄
當前指針所在行數為:25
第一次27,HJL_25,25
第二次27,HJJ_25,25
當前指針所在行數為:24
第一次26,HJL_24,24
第二次26,HJJ_24,24
當前指針所在行數為:23
第一次25,HJL_23,23
第二次25,HJJ_23,23
當前指針所在行數為:22
第一次24,HJL_22,22
第二次24,HJJ_22,22
當前指針所在行數為:21
第一次23,HJL_21,21
第二次23,HJJ_21,21
當前指針所在行數為:20
第一次22,HJL_20,20
第二次22,HJJ_20,20
當前指針所在行數為:19
第一次21,HJL_19,19
第二次21,HJJ_19,19
當前指針所在行數為:18
第一次20,HJL_18,18
第二次20,HJJ_18,18
當前指針所在行數為:17
第一次19,HJL_17,17
第二次19,HJJ_17,17
當前指針所在行數為:16
第一次18,HJL_16,16
第二次18,HJJ_16,16
當前指針所在行數為:15
第一次17,HJL_15,15
第二次17,HJJ_15,15
當前指針所在行數為:14
第一次16,HJL_14,14
第二次16,HJJ_14,14
當前指針所在行數為:13
第一次15,HJL_13,13
第二次15,HJJ_13,13
當前指針所在行數為:12
第一次14,HJL_12,12
第二次14,HJJ_12,12
當前指針所在行數為:11
第一次13,HJL_11,11
第二次13,HJJ_11,11
當前指針所在行數為:10
第一次12,HJL_10,10
第二次12,HJJ_10,10
當前指針所在行數為:9
第一次11,HJL_9,9
第二次11,HJJ_9,9
當前指針所在行數為:8
第一次10,HJL_8,8
第二次10,HJJ_8,8
當前指針所在行數為:7
第一次9,HJL_7,7
第二次9,HJJ_7,7
當前指針所在行數為:6
第一次7,HJL_6,6
第二次7,HJJ_6,6
當前指針所在行數為:5
第一次6,HJL_5,5
第二次6,HJJ_5,5
當前指針所在行數為:4
第一次5,HJL_4,4
第二次5,HJJ_4,4
當前指針所在行數為:3
第一次4,HJL_3,3
第二次4,HJJ_3,3
當前指針所在行數為:2
第一次3,HJL_2,2
第二次3,HJJ_2,2
當前指針所在行數為:1
第一次1,HJL_1,1
第二次1,HJJ_1,1
View Code

 

處理Blod數據類型:

 在數據庫中,是可以存放圖像以及音頻等二進制文件,若要存入圖像以及音頻等二進制文件,是可以通過使用SQL的blob以及mediumblob數據類型,一般都是用mediumblob數據類型,因為blob數據類型只能存儲64KB的大小文件,而mediumblob可以存儲16MB大小的文件:

create table img_table(
    img_id int auto_increment primary key,
    img_name varchar(255),
    img_data mediumblob      
)

 假設上述數據庫表有一條記錄,那么JDBC如何通過SQL查詢獲得這條記錄,以及如何處理該記錄的img_data字段數據值?在ResultSet中,可以調用getBlod(int columnIndex)方法來獲取記錄的blob或者mediumblob數據內容,該方法返回Blod對象,可以調用getBinaryStream()方法獲取該Blod數據類型(數據庫)的輸入流,或者調用getBtye()方法直接取出該Blod數據類型(數據庫)封裝的二進制數據。

 當我們向通過JDBC向數據庫寫入Blod數據類型的圖片時,由於Blod數據我們是打不出來的,因此不能使用Statement來執行SQL語句,只能通過PrepareStatement來執行語句。PrepareStatement提供了一個setBinaryStream(int parameterIndex,InputStream in)方法,該方法可以向SQL語句中的指定參數傳入二進制控制流,從而可以實現將圖片通過程序寫入到數據庫中

 下面是將一張圖片存入數據庫已經從數據庫取出該圖片的示范,(使用了上述的數據庫表,讀者先將數據庫表創建好,這里不提供創建數據表的代碼):

public class JDBC {

    String driver;
      String url;
      String user;
      String password;

public void insertBlodType(String path){
        PreparedStatement preStatement = null;
        InputStream in = null;;
        try{
            String sql = "insert into img_table values(null,?,?)";
            in = new FileInputStream(path);
            preStatement = conn.prepareStatement(sql);
            preStatement.setString(1, "img_1");
            preStatement.setBinaryStream(2, in);
            if(!preStatement.execute()){ //提交
                System.out.println("受影響了"+preStatement.getUpdateCount());
            }
            in.close();
        }catch(Exception e){
            if(preStatement != null){
                System.out.println("新增一行數據失敗");
            }
        }
    }
    
    public void queryBlodType(String path){
        PreparedStatement preStatement = null;
        try{
            String sql = "select * from img_table";
            preStatement = conn.prepareStatement(sql);
            if(preStatement.execute()){
                ResultSet resultSet = preStatement.getResultSet();
                resultSet.absolute(1);
                byte[] b= resultSet.getBytes(3);
                OutputStream out = new FileOutputStream(path);
                out.write(b);
                System.out.println("讀取並寫入成功");
                out.close();
            }
        }catch(Exception e){
            if(preStatement != null){
                System.out.println("讀取數據失敗");
            }
        }
    }
    
    Connection conn = null;
    Statement statement = null;
    public JDBC(String paramFile){
        try{
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("Url");
            user = props.getProperty("user");
            password = props.getProperty("password");
            conn =DriverManager.getConnection(url,user,password);
            statement =conn.createStatement();
            
        }catch(Exception e){}
    }
    
    public static void main(String[] args) throws SQLException {
        JDBC jdbc_2 = new JDBC("mysql.properties");
        String table = "tb_test";

        String path_1 = "D:/data/file/img.jpg";
        String famous = path_1.substring(path_1.indexOf('.'));
        String path_2 = "D:\\test"+famous;
        jdbc_2.insertBlodType(path_1);
        jdbc_2.queryBlodType(path_2);
    }
}

 運行結果為:

受影響了1
讀取並寫入成功

 實際上,我們很少將文件比如說圖片以及音頻之類的文件寫入到數據庫,主要是因為若文件寫入到了數據庫中,會導致該數據庫數據大,使用增刪改查錯誤時,也會因為文件數據大而影響速度。但我們確實要保存圖片,比如說用戶的頭像圖片,但這些圖片並不是直接寫入到數據庫中,而是寫入存儲機器的專門地方,並將指向該圖片的路徑寫入到數據庫中,這樣就減少了數據庫的存儲量。

 

使用ResultSetMetaData分析結果集:

 當執行SQL查詢后可以通過移動記錄指針來遍歷ResultSet的每條記錄,但程序可能不清楚該ResultSet里包含哪些數據列,以及每個數據列的數據類型,那么可以通過ResultSetMetaData來獲取關於ResultSet的描述信息。

 ResultSet里包含一個getMetaData()方法,該方法返回該ResultSet對應的ResultSetMetaData對象。一旦獲得該ResultSetMetaData對象,就可以通過ResultSetMetaData提供的大量方法來返回ResultSet的描述信息。常用的方法有如下三個:

  1. int getColumnCount():返回該ResultSet的列數量

  2. String getColumnName(int columnIndex):返回對應列的名稱

  3. int getColumnType(int columnIdex):返回對應列的數據類型

 下面是對ResultSetMetaData的簡單用例:

public class JDBC {

   String driver;
   String url;
   String user;
   String password;

public void ResultSetMetaDataTest(String table){
        try{
            Statement statement = conn.createStatement();
            String sql = "select * from "+table;
            ResultSet resultSet = statement.executeQuery(sql);
            ResultSetMetaData metaData = resultSet.getMetaData();
            resultSet.last();
            int rowCount = resultSet.getRow();
            int columnCount = metaData.getColumnCount();
            for(int i=0;i<=rowCount;i++){
                resultSet.absolute(i);
                for(int n=1;n<=columnCount;n++){
                    if(i == 0){
                        System.out.print(metaData.getColumnName(n)+"\n");
                    }else{
                        System.out.print(resultSet.getString(n)+"\n");
                    }
                }
                System.out.println();
            }
        }catch(Exception e){}
    }
    
    Connection conn = null;
    Statement statement = null;
    public JDBC(String paramFile){
        try{
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("Url");
            user = props.getProperty("user");
            password = props.getProperty("password");
            conn =DriverManager.getConnection(url,user,password);
            statement =conn.createStatement();
            
        }catch(Exception e){}
    }
    
    public static void main(String[] args) throws SQLException {
        JDBC jdbc_2 = new JDBC("mysql.properties");
        String table = "tb_test";
        jdbc_2.ResultSetMetaDataTest(table);
    }
}

 運行結果如下:

test_id    test_name    test_desc    
1    HJJ_1    1    
3    HJJ_2    2    
4    HJJ_3    3    
5    HJJ_4    4    
6    HJJ_5    5    
7    HJJ_6    6    
9    HJJ_7    7    
10    HJJ_8    8    
11    HJJ_9    9    
12    HJJ_10    10    
13    HJJ_11    11    
14    HJJ_12    12    
15    HJJ_13    13    
16    HJJ_14    14    
17    HJJ_15    15    
18    HJJ_16    16    
19    HJJ_17    17    
20    HJJ_18    18    
21    HJJ_19    19    
22    HJJ_20    20    
23    HJJ_21    21    
24    HJJ_22    22    
25    HJJ_23    23    
26    HJJ_24    24    
27    HJJ_25    25    
View Code

 

RowSet:

 RowSet接口繼承了ResultSet接口,RowSet接口下包含JdbcRowSet,CachedRowSet,FilteredRowSet,JoinRowSet和WebRowSet常用子接口。除了JdbcRowSet需要保持與數據庫的連接之外,其余4個子接口都是離線的RowSet,無須保存於數據庫的連接。

 與ResultSet接口相比,RowSet默認是可滾動,可更新,可序列化的結果集,並且作為對JavaBean使用,因此能方便地在網絡上傳輸,用於同步兩端的數據。對於離線RowSet而言,程序在創建RowSet時已把底層數據讀取到了內存中,因此可以充分利用計算機的內存,從而減低數據庫的負載,提高程序的性能。

 從Java 7開始,添加了RowSetProvider以及RowSetFactory的接口,其中RowSetProvider負責創建RowSetFactory接口,而RowSetFactory則提供如下方法創建RowSet實例:

  CachedRowSet createCachedRowSet(): 創建一個默認的CachedRowSet。

  FilteredRowSet createFilteredRowSet():  創建一個默認的FilteredRowSet。

  JdbcRowSet createJdbcRowSet(): 創建一個默認的JdbcRowSet。

  JoinRowSet createJoinRowSet(): 創建一個默認的JoinRowSet。

  WebRowSet createWebRowSet():創建一個默認的WebRowSet。

  在Java 7之前,如果程序需要使用JdbcPowSet,是通過調用JdbcPowSetImpl的構造器來創建JdbcRowSet實例的,不過現在都是通過上述方法來創建JdbcRowSet實例的。

 

 RowSet接口還定義了如下常用方法:

  setUrl(Stirng url):設置該RowSet要訪問的數據庫的URL。

  setUsername(String username):設置該RowSet要訪問的數據庫的用戶名。

  setPassword(String password):設置該RowSet要訪問的數據庫的密碼。

  setCommand(String sql):設置使用該sql語句的查詢結果來裝填該RowSet

  execute(): 執行查詢

  populate(ResultSet rs):讓該RowSet直接包裝給定的RsultSet對象。

 

 以下是對RowSet的簡單程序(JdbcRowSet):

public class JDBC {
    String driver;
    String url;
    String user;
    String password;
    
    public void rowSetFactoryTest(String sql){
        try{
            RowSetFactory factory = RowSetProvider.newFactory();
            JdbcRowSet jdbcRowSet = factory.createJdbcRowSet();
            jdbcRowSet.setUrl(url);
            jdbcRowSet.setUsername(user);
            jdbcRowSet.setPassword(password);
            
            jdbcRowSet.setCommand(sql);
            jdbcRowSet.execute();
            while(jdbcRowSet.next()){
                System.out.println("當前指針所在行數為:"+jdbcRowSet.getRow());
                System.out.println("第一次"+jdbcRowSet.getString(1)+","+jdbcRowSet.getString(2)+","+jdbcRowSet.getString(3));
                jdbcRowSet.updateString(2, "HJJ_");
                jdbcRowSet.updateRow();
                System.out.println("第二次"+jdbcRowSet.getString(1)+","+jdbcRowSet.getString(2)+","+jdbcRowSet.getString(3));
            }
        }catch(Exception e){}
    }
    
    Connection conn = null;
    Statement statement = null;
    public JDBC(String paramFile){
        try{
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("Url");
            user = props.getProperty("user");
            password = props.getProperty("password");
            conn =DriverManager.getConnection(url,user,password);
            statement =conn.createStatement();
            
        }catch(Exception e){}
    }

    public static void main(String[] args) throws SQLException {
        // TODO Auto-generated method stub

        JDBC jdbc_2 = new JDBC("mysql.properties");
        String table = "tb_test";
        String sql = "select * from "+table;
        jdbc_2.rowSetFactoryTest(sql);
    }
}

 運行結果如下:

當前指針所在行數為:1
第一次1,HJJ_1,1
第二次1,HJJ_,1
當前指針所在行數為:2
第一次3,HJJ_2,2
第二次3,HJJ_,2
當前指針所在行數為:3
第一次4,HJJ_3,3
第二次4,HJJ_,3
當前指針所在行數為:4
第一次5,HJJ_4,4
第二次5,HJJ_,4
當前指針所在行數為:5
第一次6,HJJ_5,5
第二次6,HJJ_,5
當前指針所在行數為:6
第一次7,HJJ_6,6
第二次7,HJJ_,6
當前指針所在行數為:7
第一次9,HJJ_7,7
第二次9,HJJ_,7
當前指針所在行數為:8
第一次10,HJJ_8,8
第二次10,HJJ_,8
當前指針所在行數為:9
第一次11,HJJ_9,9
第二次11,HJJ_,9
當前指針所在行數為:10
第一次12,HJJ_10,10
第二次12,HJJ_,10
當前指針所在行數為:11
第一次13,HJJ_11,11
第二次13,HJJ_,11
當前指針所在行數為:12
第一次14,HJJ_12,12
第二次14,HJJ_,12
當前指針所在行數為:13
第一次15,HJJ_13,13
第二次15,HJJ_,13
當前指針所在行數為:14
第一次16,HJJ_14,14
第二次16,HJJ_,14
當前指針所在行數為:15
第一次17,HJJ_15,15
第二次17,HJJ_,15
當前指針所在行數為:16
第一次18,HJJ_16,16
第二次18,HJJ_,16
當前指針所在行數為:17
第一次19,HJJ_17,17
第二次19,HJJ_,17
當前指針所在行數為:18
第一次20,HJJ_18,18
第二次20,HJJ_,18
當前指針所在行數為:19
第一次21,HJJ_19,19
第二次21,HJJ_,19
當前指針所在行數為:20
第一次22,HJJ_20,20
第二次22,HJJ_,20
當前指針所在行數為:21
第一次23,HJJ_21,21
第二次23,HJJ_,21
當前指針所在行數為:22
第一次24,HJJ_22,22
第二次24,HJJ_,22
當前指針所在行數為:23
第一次25,HJJ_23,23
第二次25,HJJ_,23
當前指針所在行數為:24
第一次26,HJJ_24,24
第二次26,HJJ_,24
當前指針所在行數為:25
第一次27,HJJ_25,25
第二次27,HJJ_,25
View Code

 

 離線RowSet:

  我們可以看到,使用了RowSet也可以實現對結果集的可滾動以及可更新。但看上上述程序,估計很多人都會想問,既然用ResultRow用的好好的,怎么突然增加了RowSet的用法,主要是因為RowSet不僅可以實現ResultRow的功能,主要的就是RowSet是支持離線的,這是ResultRow所擁有不了的,我們可以通過下面程序來觀察RowSet與ResultRow:

public class JDBC {
    String driver;
    String url;
    String user;
    String password;
    public void CachedRowSetTest(String sql){
        ResultSet resultSet = null;
        CachedRowSet cachedRowSet = null;
        try{
            Statement statement = conn.createStatement();
            resultSet = statement.executeQuery(sql);

            RowSetFactory factory = RowSetProvider.newFactory();
            cachedRowSet = factory.createCachedRowSet();
            
            cachedRowSet.populate(resultSet); //使用ResultSet裝填RowSet
            
            resultSet.last();cachedRowSet.last();
            System.out.println("資源開啟前,cachedRowSet查詢行數一共為"+cachedRowSet.getRow()+"行");
            System.out.println("資源開啟前,resultSet查詢行數一共為"+resultSet.getRow()+"行");
            //關閉資源
            conn.close();
            if(cachedRowSet.getRow() >0){
                System.out.println("資源關閉后,cachedRowSet查詢行數一共為"+cachedRowSet.getRow()+"行");
                while(cachedRowSet.previous()){ //向上滾動結果集
                    System.out.println("當前指針所在行數為:"+cachedRowSet.getRow());
                    System.out.println("第一次"+cachedRowSet.getString(1)+","+cachedRowSet.getString(2)+","+cachedRowSet.getString(3));
                    cachedRowSet.updateString(2, "HJL_"+cachedRowSet.getRow());
                    cachedRowSet.updateRow();
                    if(cachedRowSet.getRow() == 1){
                        break;
                    }
                }
                
                //重新連接數據庫
                conn = DriverManager.getConnection(url, user, password);
                conn.setAutoCommit(false);
                cachedRowSet.acceptChanges(conn); //把對cachedRowSet所做的修改同步到底層數據庫
                while(cachedRowSet.next()){
                    System.out.println("當前指針所在行數為:"+cachedRowSet.getRow());
                    System.out.println("第二次"+cachedRowSet.getString(1)+","+cachedRowSet.getString(2)+","+cachedRowSet.getString(3));
                }
                conn.close();   //關閉數據庫
            }
            if(resultSet.getRow() >0){
                System.out.println("資源關閉后,resultSet查詢行數一共為"+resultSet.getRow()+"行");                
            }
            
        }catch(Exception e){}
    }
    
    Connection conn = null;
    Statement statement = null;
    public JDBC(String paramFile){
        try{
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("Url");
            user = props.getProperty("user");
            password = props.getProperty("password");
            conn =DriverManager.getConnection(url,user,password);
            statement =conn.createStatement();
            
        }catch(Exception e){}
    }

    public static void main(String[] args) throws SQLException {
        JDBC jdbc_2 = new JDBC("mysql.properties");
        String table = "tb_test";
        String sql = "select * from "+table;
        jdbc_2.CachedRowSetTest(sql);
    }
}

  運行結果如下:

資源開啟前,cachedRowSet查詢行數一共為25行
資源開啟前,resultSet查詢行數一共為25行
資源關閉后,cachedRowSet查詢行數一共為25行
當前指針所在行數為:24
第一次26,HJJ_24,24
當前指針所在行數為:23
第一次25,HJJ_23,23
當前指針所在行數為:22
第一次24,HJJ_22,22
當前指針所在行數為:21
第一次23,HJJ_21,21
當前指針所在行數為:20
第一次22,HJJ_20,20
當前指針所在行數為:19
第一次21,HJJ_19,19
當前指針所在行數為:18
第一次20,HJJ_18,18
當前指針所在行數為:17
第一次19,HJJ_17,17
當前指針所在行數為:16
第一次18,HJJ_16,16
當前指針所在行數為:15
第一次17,HJJ_15,15
當前指針所在行數為:14
第一次16,HJJ_14,14
當前指針所在行數為:13
第一次15,HJJ_13,13
當前指針所在行數為:12
第一次14,HJJ_12,12
當前指針所在行數為:11
第一次13,HJJ_11,11
當前指針所在行數為:10
第一次12,HJJ_10,10
當前指針所在行數為:9
第一次11,HJJ_9,9
當前指針所在行數為:8
第一次10,HJJ_8,8
當前指針所在行數為:7
第一次9,HJJ_7,7
當前指針所在行數為:6
第一次7,HJJ_6,6
當前指針所在行數為:5
第一次6,HJJ_5,5
當前指針所在行數為:4
第一次5,HJJ_4,4
當前指針所在行數為:3
第一次4,HJJ_3,3
當前指針所在行數為:2
第一次3,HJJ_2,2
當前指針所在行數為:1
第一次1,HJJ_1,1
當前指針所在行數為:1
第二次3,HJL_2,2
當前指針所在行數為:2
第二次4,HJL_3,3
當前指針所在行數為:3
第二次5,HJL_4,4
當前指針所在行數為:4
第二次6,HJL_5,5
當前指針所在行數為:5
第二次7,HJL_6,6
當前指針所在行數為:6
第二次9,HJL_7,7
當前指針所在行數為:7
第二次10,HJL_8,8
當前指針所在行數為:8
第二次11,HJL_9,9
當前指針所在行數為:9
第二次12,HJL_10,10
當前指針所在行數為:10
第二次13,HJL_11,11
當前指針所在行數為:11
第二次14,HJL_12,12
當前指針所在行數為:12
第二次15,HJL_13,13
當前指針所在行數為:13
第二次16,HJL_14,14
當前指針所在行數為:14
第二次17,HJL_15,15
當前指針所在行數為:15
第二次18,HJL_16,16
當前指針所在行數為:16
第二次19,HJL_17,17
當前指針所在行數為:17
第二次20,HJL_18,18
當前指針所在行數為:18
第二次21,HJL_19,19
當前指針所在行數為:19
第二次22,HJL_20,20
當前指針所在行數為:20
第二次23,HJL_21,21
當前指針所在行數為:21
第二次24,HJL_22,22
當前指針所在行數為:22
第二次25,HJL_23,23
當前指針所在行數為:23
第二次26,HJL_24,24
當前指針所在行數為:24
第二次27,HJJ_,25
View Code

  我們可以看到運行結果,當conn關閉時,從statement返回的結果集合進入不了判斷語句中,而將該結果集合給予了CachedRowSet后,是可以進入判斷語句里,並對該集合進行了更新操作。不過這個更新操作需要等到數據庫連接后提交方可生效,否則是無效的。

 

 離線RowSet的查詢分頁:

  由於支持RowSet離線的子接口都是將數據直接轉載到內存中,因此如果SQL查詢返回的記錄過大,CachedRowSet便會占用大量的內存,在某些極端的情況下,它甚至會導致內存溢出。

  為了解決該問題,CachedRowSet提供了分頁功能,一次只裝載ResultSet里的某幾條記錄,這樣就可以避免占用過多內存的問題。

  CachedRowSet提供了如下方法來控制分頁:

   populate(ResultSet ,int startRow); 使用給定的ResultSet裝填RowSet,從ResultSet的第startRow條記錄開始裝填。

   setPageSize(int pageSize):設置CachedRowSet每次返回多少條記錄

   previousPage() :在底層ResultSet可用的情況下,讓CachedRowSet讀取上一頁記錄

   nextPage():在底層ResultSet可用的情況下,讓CachedRowSet讀取下一頁記錄

  下面程序示范了CachedRowSet的分頁支持:

public class JDBC {
    String driver;
    String url;
    String user;
    String password;
    public void cachedRowSetPage(String sql,int pageSize,int page){
        try{
            Statement statement = conn.createStatement();
            ResultSet resultSet = statement.executeQuery(sql);    
            
            RowSetFactory factory = RowSetProvider.newFactory();
            CachedRowSet cachedRowSet = factory.createCachedRowSet();
            
            page = page -1;
            if(page<0){
                page = 0;
            }
            
            cachedRowSet.setPageSize(pageSize);
            cachedRowSet.populate(resultSet,(page-1)*pageSize+1); //將對應數據存入內存中
            
            int count = 0;
            while(cachedRowSet.next()){
                System.out.println("當前指針所在行數為:"+cachedRowSet.getRow());
                System.out.println(cachedRowSet.getString(1)+","+cachedRowSet.getString(2)+","+cachedRowSet.getString(3));
                count++;
            }
            System.out.println("共"+count+"條數據");
        }catch(Exception e){}
    }
    
    Connection conn = null;
    Statement statement = null;
    public JDBC(String paramFile){
        try{
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("Url");
            user = props.getProperty("user");
            password = props.getProperty("password");
            conn =DriverManager.getConnection(url,user,password);
            statement =conn.createStatement();
            
        }catch(Exception e){}
    }

    public static void main(String[] args) throws SQLException {

        JDBC jdbc_2 = new JDBC("mysql.properties");
        String table = "tb_test";
        String sql = "select * from "+table;
        jdbc_2.cachedRowSetPage(sql,3,2);
    }
}

  運行結果如下:

當前指針所在行數為:1
1,HJL_1,1
當前指針所在行數為:2
3,HJL_2,2
當前指針所在行數為:3
4,HJL_3,3
共3條數據

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM