jdbc:ResultSet Types--ResultSet Concurrency--Cursor Holdability

官网地址:https://docs.oracle.com/javase/tutorial/jdbc/basics/retrieving.html

1 ResultSet Types

    主要有两个影响 :1游标是否能灵活的移动 2当数据库有变动时(其他进程修改),ResultSet结果是否会更新

    参数有三:

                   1 TYPE_FORWARD_ONLY(官网让使用ResultSet. TYPE_SCROLL_SENSITIVE调用,实际要ResultSetImpl. TYPE_SCROLL_SENSITIVE)

     指针只能后移,即只能调用rs.next(),rs不会及时更新数据库的变得(这是不被支持的)

                   2 TYPE_SCROLL_INSENSITIVE

     指针能任意移动调用next,prviou以及其他method,rs不会及时更新数据库的变得

                   3 TYPE_SCROLL_SENSITIVE

     指针能任意移动调用next,prviou以及其他method,rs会及时更新数据库的变得(在下面的测试代码中,这是不被支持的)

2 ResultSet Concurrency

    是否能对rs进行修改(rs并不只是用于读取数据,rs是一个保持链接的数据集,当con被关闭,rs也会失效;所以这种改动可以被持久化到数据库,详见测试代码)

    参数有二:

                   1 CONCUR_READ_ONLY :不能修改

                   2 CONCUR_UPDATABLE: 能修改

3 Cursor Holdability

当执行了con.commit:执行了事务提交,rs的游标应该保持在原位置,或是回到rs的头部(beforeFirst)

1 HOLD_CURSORS_OVER_COMMIT :保持在原位置
2 CLOSE_CURSORS_AT_COMMIT:回到rs的头部

我的测试环境:mysql

       不同的数据库官方,对jdbc的实现可能不一致,有些特性不一定是被支持的。所以以下代码只能是mysql。

       例如mysql对 ResultType的TYPE_FORWARD_ONLY根本无法调用;

       而对ResultType的TYPE_SCROLL_SENSITIVE,查看是false。

 

我的测试代码:

1 类JdbcT

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.DatabaseMetaData;
import com.mysql.jdbc.ResultSetImpl;
import com.mysql.jdbc.Statement;
import org.junit.Test;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JdbcT {
    @Test
    public void test() throws ClassNotFoundException, SQLException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection con = (Connection) DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/cesium", "root", "root");
        Statement st = (Statement) con.createStatement(
                ResultSetImpl.TYPE_SCROLL_SENSITIVE,
                ResultSetImpl.CONCUR_UPDATABLE,
                ResultSetImpl.CLOSE_CURSORS_AT_COMMIT);
        ResultSet rs = st.executeQuery("select * from user");
        DatabaseMetaData databaseMetaData = (DatabaseMetaData) con.getMetaData();
        /*
            1 游标是否可以灵活移动,灵敏度,同步db读取后的修改
            DatabaseMetaData.supportsResultSetType
            TYPE_FORWARD_ONLY:游标只能next,不能previous以及其他所有的移动游标method,数据库有改动,不会及时更新
                next:将光标向前移动一行。返回true如果光标现位于一行,并false当光标位于最后一行之后。
                previous:将光标向后移动一排。返回true如果光标现位于一行,并false当光标位于第一行之前。
                first:将光标移动到ResultSet对象的第一行。返回true如果光标现位于第一行上false,如果ResultSet对象不包含任何行。
                last::将光标移动到ResultSet对象的最后一行。返回true如果光标现位于最后一排并false如果ResultSet对象不包含任何行。
                beforeFirst:将光标置于ResultSet对象的开头,第一行之前。如果ResultSet对象不包含任何行,则此方法无效。
                afterLast:将光标置于ResultSet对象的末尾,最后一行之后。如果ResultSet对象不包含任何行,则此方法无效。
                relative(int rows):相对于其当前位置移动光标。
                absolute(int row):将光标定位在参数指定的行上row。
            TYPE_SCROLL_INSENSITIVE: (不敏感的)游标能双向移动,但是获取了rs之后,数据库有改动,不会及时更新
            TYPE_SCROLL_SENSITIVE:  游标能双向移动,获取了rs之后,数据库有改动,会及时更新
         */
        // 没有第一种,应该是不支持
        System.out.println("游标可移动不敏感:"+
                databaseMetaData.supportsResultSetType(ResultSetImpl.TYPE_SCROLL_INSENSITIVE)
        );
        System.out.println("游标可移动且敏感:"+
                databaseMetaData.supportsResultSetType(ResultSetImpl.TYPE_SCROLL_SENSITIVE)
        );
        /*  2 并发:修改rs
            DatabaseMetaData.supportsResultSetConcurrency
            CONCUR_READ_ONLY: The ResultSet object cannot be updated using the ResultSet interface.
                读取出来的rs,不能后期修改
            CONCUR_UPDATABLE: The ResultSet object can be updated using the ResultSet interface.
                 读取出来的rs,能后期修改
         */
        System.out.println("游标可移动且敏感,数据不可修改:"+//因为 TYPE_SCROLL_SENSITIVE false
                databaseMetaData.supportsResultSetConcurrency(ResultSetImpl.TYPE_SCROLL_SENSITIVE, ResultSetImpl.CONCUR_READ_ONLY)
        );
        System.out.println("游标可移动且敏感,数据修改:"+//因为 TYPE_SCROLL_SENSITIVE false
                databaseMetaData.supportsResultSetConcurrency(ResultSetImpl.TYPE_SCROLL_SENSITIVE, ResultSetImpl.CONCUR_UPDATABLE)
        );
        //
        System.out.println("游标可移动不敏感,数据不可修改:"+
                databaseMetaData.supportsResultSetConcurrency(ResultSetImpl.TYPE_SCROLL_INSENSITIVE, ResultSetImpl.CONCUR_READ_ONLY)
        );
        System.out.println("游标可移动不敏感,数据修改:"+
                databaseMetaData.supportsResultSetConcurrency(ResultSetImpl.TYPE_SCROLL_INSENSITIVE, ResultSetImpl.CONCUR_UPDATABLE)
        );
        /* 3 游标持久保留
            databaseMetaData.supportsResultSetHoldability
            HOLD_CURSORS_OVER_COMMIT:事务结束后(Connection.commit),游标位置保留(rs不置null?),可能提高一些性能
            CLOSE_CURSORS_AT_COMMIT:
         */
        System.out.println("ResultSet.HOLD_CURSORS_OVER_COMMIT = " +
                ResultSetImpl.HOLD_CURSORS_OVER_COMMIT);
        System.out.println("ResultSet.CLOSE_CURSORS_AT_COMMIT = " +
                ResultSetImpl.CLOSE_CURSORS_AT_COMMIT);

        System.out.println("Default cursor holdability: " +
                databaseMetaData.getResultSetHoldability());
        System.out.println("游标保留:"+
                databaseMetaData.supportsResultSetHoldability(ResultSetImpl. HOLD_CURSORS_OVER_COMMIT)
        );
        System.out.println("游标不保留:"+
                databaseMetaData.supportsResultSetHoldability(ResultSetImpl. CLOSE_CURSORS_AT_COMMIT)
        );
    }
}
2 类JdbcT2

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.DatabaseMetaData;
import com.mysql.jdbc.ResultSetImpl;
import com.mysql.jdbc.Statement;
import org.junit.Test;

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JdbcT2 {
    @Test
    public void test1() throws ClassNotFoundException, SQLException, InterruptedException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection con = (Connection) DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/cesium", "root", "root");
        con.setAutoCommit(false);// 必须设置,才能手动提交
        Statement st = (Statement) con.createStatement(
                ResultSetImpl.TYPE_SCROLL_SENSITIVE,
                ResultSetImpl.CONCUR_UPDATABLE,
                ResultSetImpl.CLOSE_CURSORS_AT_COMMIT);
        ResultSet rs = st.executeQuery("select * from user");
        DatabaseMetaData databaseMetaData = (DatabaseMetaData) con.getMetaData();
        if(rs.next()){
            Integer i = rs.getInt("id");
            System.out.println(i);
            rs.updateInt("id",10);// 这个更新是会被写回数据库的,应该是隐式的使用了事务,锤子:statement就是事务
            rs.updateRow();// 这一行类似与commit。不写上一行不会起效
        }
        System.out.println(rs.getInt("id"));
        // 测试commit后的游标保留
        rs.next();
        con.commit();
        // 虽然设置了关闭游标,但是实际没有关闭,因为JdbcT里面测过,mysql是不支持提交关闭游标的
        System.out.println(rs.getInt("id"));

    }

    // 测试第一个参数,db敏感,游标移动不用测,只有这一个选项,没有不可移动
    public static void main(String[] args) throws ClassNotFoundException, SQLException, InterruptedException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection con = (Connection) DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/cesium", "root", "root");
        Statement st = (Statement) con.createStatement(
                ResultSetImpl.TYPE_SCROLL_SENSITIVE,
                ResultSetImpl.CONCUR_UPDATABLE,
                ResultSetImpl.CLOSE_CURSORS_AT_COMMIT);
        ResultSet rs = st.executeQuery("select * from user");
        DatabaseMetaData databaseMetaData = (DatabaseMetaData) con.getMetaData();

        while(rs.next()){
            // 在sleep的时候,改变第二行的数据,并没有及时的更新,
            // 调用ResultSetImpl.TYPE_SCROLL_SENSITIVE,是无效的。
            // 在上一个类中测试过,虽然有参数,但是out的是不支持(false)
            System.out.println("col1:"+rs.getObject(1));
            System.out.println("col2:"+rs.getObject(2));
            Thread.sleep(10000);
        }
    }
}

三-结果分析

1 ResultSet Types

mysql对 ResultType的TYPE_FORWARD_ONLY根本无法调用;

       而对ResultType的TYPE_SCROLL_SENSITIVE,查看是false。

2 ResultSet Concurrency

数据会持久化到数据库,不只是rs本身。或许rs本身就是一个指针集合??不去看底层了

3 Cursor Holdability

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值