• 管理结果集(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)+"
    ");
                        }else{
                            System.out.print(resultSet.getString(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条数据

      

  • 相关阅读:
    python字典
    python元组
    python list列表
    deepin常用操作
    Be a child.Be a man...
    “夹心阶层”——面对高昂的房价,要面对现实,广州,除了劳动力便宜,什么都贵。
    男人一生中16件事情(转载)
    被老板臭骂了一顿,但受益匪浅。
    陪伴
    高品质生活
  • 原文地址:https://www.cnblogs.com/hjlin/p/11442481.html
Copyright © 2020-2023  润新知