JavaJDBC结果集的处理
结果集指针的移动
while (()){
//......
}
指针最初指向第⼀条记录之前,next()是指向下⼀个位置,返回的是boolean值,true表⽰有内容(记录),false表⽰⽆内容(false)。
如果当前是指向最后⼀条记录,next()就指向最后⼀条记录之后,返回false,退出循环,遍历完成。
准确地说,应该叫做游标(Cursor),学C++的时候叫指针(Pointer)叫习惯了......
//下⾯3种都是相对当前位置的移动
<();  //指针移到下⼀个位置
resultSet.previous();  //指针移到前⼀个位置
      lative(2);  //相对当前位置后移2步
      lative(-1);  //正数表⽰后移,负数表⽰前移。相对当前位置前移1步。
//下⾯5种都是绝对位置的移动
      resultSet.absolute(n); //指向结果集中的第n+1条记录,n是下标,0表⽰第⼀条记录
resultSet.first();  //指针移到第⼀条记录上
resultSet.last();  //指针移到最后⼀条记录上
resultSet.beforeFirst();  //指针移到第⼀条记录之前
resultSet.afterLast();  //指针移到最后⼀条记录之后
/
/对应的判断⽅法
resultSet.isFirst();
resultSet.isLast();
resultSet.isBeforeFirst();
resultSet.isAfterLast();
获取结果集中的记录总数
1if(resultSet.last()) {  //指针移到最后⼀条记录上,使⽤if是因为结果集可能是空的,要先判断
2            System.out.Row());  //getRow()是返回当前记录是结果集中的第⼏条记录,int型
3    }
离线查询
如果要长期使⽤结果集中的数据,以前有2种⽅式:
⼀直保持数据库连接,不关闭。如果保持的连接很多,服务器、数据库的性能都会受到影响。
将结果集中的记录存储到多个JavaBean中,数据库没影响,但要编写JavaBean,写代码遍历结果集,将每⾏记录赋给JavaBean,⾃⼰写代码的话很⿇烦。如果记录很多,创建⼤量的JavaBean是很花时间的,JVM要管理⼤量的JavaBean对象,开销很⼤,程序性能
降低;且操作结果集⽐操作JavaBean的集合要简单。
离线查询:在本地搞⼀个结果集的副本,关闭结果集、数据库连接,使⽤本地的这个副本。
ResultSet接⼝有⼦接⼝RowSet,RowSet有⼦接⼝CachedRowSet。离线查询就是通过CachedRowSet来实现的。
1//从properties⽂件中加载数据库配置
2        Properties properties = new Properties();
3        InputStream inputStream =Class.forName("test.Test").getResourceAsStream("/mysql.properties");
4        properties.load(inputStream);
5
6        String driver = Property("driver");
7        String url = Property("url");
8        String user = Property("user");
9        String Property("password");
10
11        Class.forName(driver);
12        Connection connection = Connection(url, user, pwd);
13
14        String sql = "select * from student_tb";
15        PreparedStatement preparedStatement = connection.prepareStatement(sql);
16        ResultSet resultSet = uteQuery();
17
18//离线查询
19        RowSetFactory rowSetFactory = wFactory();  //通过RowSetProvider的静态⽅法创建RowSetFactory对象
20        CachedRowSet cachedRowSet = ateCachedRowSet();  //创建CachedRowSet对象
21        cachedRowSet.populate(resultSet);  //使⽤结果集填充cachedRowSet
22//cachedRowSet.populate(resultSet,2);  //可指定从结果集的第⼏条记录开始填充,默认为1,从第⼀条记录开始填充
23
24//关闭数据库资源
resultset 遍历
25        resultSet.close();
26        preparedStatement.close();  //关闭Statement|PreparedStatement对象
27        connection.close();
28
29//CachedRowSet是ResultSet的孙接⼝,继承了ResultSet的属性、⽅法,使⽤⽅式和ResultSet⼀样
()){
31int id = Int("id");
32            String name =String("name");
33int age = Int("age");
34float score = Float("score");
35            System.out.println(id+"\t"+name+"\t"+age+"\t"+score);
36        }
更新结果集
ResultSet默认是可滚动的、不可更新的,不能删除、修改结果集中的记录。如果要获取可更新的结果集(可增删改结果集中的记录),需要在创建Statement | PreparedStatement对象时传⼊2个额外的参数。
CachedRowSet默认是可滚动的、可更新的,可删除、修改CachedRowSet中的记录。
可滚动指的是可以使⽤next()、first()、last()、absolute()等⽅法移动游标,不可滚动指的是只能使⽤next()来移动游标。
可更新的ResultSet:
1//从properties⽂件中加载数据库配置
2        Properties properties = new Properties();
3        InputStream inputStream =Class.forName("test.Test").getResourceAsStream("/mysql.properties");
4        properties.load(inputStream);
5
6        String driver = Property("driver");
7        String url = Property("url");
8        String user = Property("user");
9        String Property("password");
10
11        Class.forName(driver);
12        Connection connection = Connection(url, user, pwd);
14        String sql = "select * from student_tb";
15/*
16获取可更新的结果集
17
18第⼆个参数指定结果集是否是可滚动的:
19        ResultSet.TYPE_FORWARD_ONLY  不可滚动,只能使⽤next()移动游标
20        ResultSet.TYPE_SCROLL_SENSITIVE  可滚动,底层数据的变化会同步到结果集(需要底层数据库驱动的⽀持)
21        ResultSet.TYPE_SCROLL_INSENSITIVE  可滚动,底层数据的变化不会同步到结果集
22
23第三个参数指定结果集是否是可更新的:
24        ResultSet.CONCUR_READ_ONLY  默认值,只读
25        ResultSet.CONCUR_UPDATABLE  可更新(对结果集中的记录可增删改)
26*/
27        PreparedStatement preparedStatement = connection.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
28        ResultSet resultSet = uteQuery();
29
30while (()){
31int id = Int("id");
32if(id==5){
33//updateXxx()修改当前记录某个字段的值,第⼀个参数指定列(字段),可以⽤列名或列索引,第⼆个参数指定新值
34                resultSet.updateString("name","chy");  //修改当前记录的name字段的值为chy
35                resultSet.updateRow();  //将对结果集中记录的改同步到数据库中,改不会⾃动同步到数据库中,需要⼿动同步
36            }
37else if(id==10){
38                resultSet.deleteRow();  //删除当前记录(删除当前⾏),删会⾃动同步到数据库中
39            }
40        }
41
42//往结果集中插⼊⼀⾏
43        veToInsertRow();
44/*
45通过updateXxx()设置插⼊⾏的字段值
46
47        resultSet.updateInt("id",100);
48如果不设置主键列(id)的值,默认插到结果集的末尾,
49如果结果集中没有id=100的记录,但数据库中有,同步到数据库时会出错
50*/
51        resultSet.updateString("name","CoCo");
52        resultSet.updateInt("age",20);
53        resultSet.updateInt("score",90);
54
55        resultSet.insertRow();  //将增同步到数据库
56
57//这期间需要保持数据库连接
58
59        resultSet.close();
60        preparedStatement.close();
61        connection.close();
update、insert需要⼿动同步,delete却是⾃动同步,why?
因为delete是⼀步操作,update、insert均是多步操作,update可能要updateXxx()修改多个字段,insert可能要updateXxx()插⼊多个字段的值,JVM不知道你的updateXxx()写完了没有,所以要写resultSet.updateRow()|insertRow();  告诉JVM:我对这条记录的改|插⼊字段已经弄完了,JVM才会同步到数据库中。
注意是updateRow()、insertRow()、deleteRow(),是Row,不是Rows,同步的只是⼀条记录。
所以每操作完⼀条记录,该⼿动同步的就要⼿动同步,不能想着⼀次性同步所有更新。
CachedRowSet的更新操作:
1//从properties⽂件中加载数据库配置
2        Properties properties = new Properties();
3        InputStream inputStream =Class.forName("test.Test").getResourceAsStream("/mysql.properties");
4        properties.load(inputStream);
5
6        String driver = Property("driver");
7        String url = Property("url");
8        String user = Property("user");
9        String Property("password");
11        Class.forName(driver);
12        Connection connection = Connection(url, user, pwd);
13
14        String sql = "select * from student_tb";
15        PreparedStatement preparedStatement = connection.prepareStatement(sql);  //CachedRowSet默认就是可更新的,不必传额外的参数
16        ResultSet resultSet = uteQuery();
17        ();
18
19//离线结果集
20        RowSetFactory rowSetFactory = wFactory();
21        CachedRowSet cachedRowSet = ateCachedRowSet();
22        cachedRowSet.populate(resultSet);
23        resultSet.close();
24        preparedStatement.close();
25        connection.close();
26
27while (()){
28int id = Int("id");
29if (id==15){
30//删除记录
31                cachedRowSet.deleteRow();
32            }
33else if(id==20){
34//修改记录
35                cachedRowSet.updateString("name","chy1");
36                cachedRowSet.updateRow();
37            }
38        }
39
40        Connection connection1 = Connection(url, user, pwd);  //连接已关闭了,需要重新获取⼀个连接
41        connection1.setAutoCommit(false);  //将新连接的⾃动提交设置为false
42        cachedRowSet.acceptChanges(connection1);  //同步到数据库。
对CachedRowSet使⽤deleteRow()、updateRow()不会⽴刻同步到数据库中,因为连接已经关闭了,同步不了。
这2个⽅法相当于把这些同步操作放在⼀个队列中,当  cachedRowSet.acceptChanges(connection1);
  传⼊⼀个连接时,就依次执⾏队列中的同步操作。
CachedRowSet不能插⼊⼀条记录,因为CachedRowSet是批量同步的(队列),插⼊操作可能会受到队列中其他记录的影响。CachedRowSet是默认可更新的,不是默认⾃动提交的。
更新操作要求结果集满⾜2个条件:
结果集只能是单表查询的结果集
结果集中必须含有主键列
分页
分页有3种实现⽅式。
1、使⽤sql语句来限定结果集范围
1 String sql = "select * from student_tb where id>? and id<?";
2        PreparedStatement preparedStatement = connection.prepareStatement(sql);
3        preparedStatement.setInt(1,0);
4        preparedStatement.setInt(2,11);
5        ResultSet resultSet = uteQuery();
这种⽅式不好,因为区间上的某些记录可能被删除了,id没了。⽐如1页10条记录,[1,10],但id=5,id=8的记录被删除了(⽐如注销账户),实际取到的就⽐10条少。
1 String sql = "select * from student_tb limit ?,?";
2        PreparedStatement preparedStatement = connection.prepareStatement(sql);
3        preparedStatement.setInt(1,0);  //从满⾜条件的记录中的第1条记录起(参数是下标)
4        preparedStatement.setInt(2,10);  //只取10条记录
5/*
6第⼀个参数可缺省,默认为0,从第⼀条记录起。
7        String sql = "select * from student_tb limit 100"; 只取100条记录
8*/
能取⾜10条,但limit是mysql的特性,对应的SQL  Server特性是top、Oracle特性是rownum,不跨数据库。
2、使⽤游标来实现
1  String sql = "select * from student_tb";
2        PreparedStatement preparedStatement = connection.prepareStatement(sql);
3        ResultSet resultSet = uteQuery();
4
5int start=0;  //开始位置
6int pageSize=10;  //每页显⽰多少条记录
7        resultSet.absolute(start);  //先转到起始处。参数是下标,0表⽰第⼀条记录
8while (()){
9//......
10            System.out.Row());
Row()==start+pageSize)  //getRow()是获取当前记录是结果集中的第⼏条记录,第⼀条就是1。也可以设置计数器来判断12break;
13        }
3、使⽤离线查询来实现
1//离线结果集
2        RowSetFactory rowSetFactory = wFactory();
3        CachedRowSet cachedRowSet = ateCachedRowSet();
4        cachedRowSet.setPageSize(10);  //设置每页显⽰多少条记录,其实设置的是CachedRowSet的容量
5        cachedRowSet.populate(resultSet,1);  //设置从结果集中的第⼏条记录开始填充。cachedRowSet中的记录是结果集中的[1,10]条
6        resultSet.close();
7        preparedStatement.close();
8        connection.close();
9
10while (()){
11//......
12        }

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。