[疯狂Java]JDBC:可滚动/可更新的ResultSet

1. 之前还有一个大问题没有解决:为什么ResultSet时刻都保持着跟Connection的绑定(Connection关闭ResultSet也被关闭)

    1) 其实你可能猜到了,ResultSet还有我们之前没有用到的功能,ResultSet肯定是时刻(实时)跟Connection保持着连接的,也许数据库相应数据的改变也能及时地更新ResultSet中相应的内容;

    2) 答案是正确的,实际上如果ResultSet的功能全部开启的话不仅会实时保持跟Connection的连接(数据库中数据改变也会自动及时更新ResultSet中的内容),而且对ResultSet中内容的修改也可以反过来更新数据库中的内容!!!

!!也就是说ResultSet其实是一种直接跟数据库交互的通道(注意!是直接交互!),因此这条通道必然会被同不监视、和Connection同生死!!

    3) ResultSet可以开启的全部三大功能:

         a. 滚动:在JDK1.4之前默认打开的ResultSet默认只能使用next一个方法移动记录指针,这种就是不可滚动的,而可滚动的是指可以使用全部的指针移动方法来定位记录指针(previous、last、afterlast等);

         b. 敏感:即底层数据库中相应数据的更新会实时同步到相应的ResultSet,如果没有这项功能则是不敏感的;

         c. 并发:并发有两种,一种是只读并发(即ResultSet中的记录只读不能修改,默认),另一种是可更新并发(即ResultSet中的记录可以修改,并且修改后还可以直接更新相应数据库中的记录);

!!如果开启了可更新并发,那么ResultSet即使可更新的;


2. 开启ResultSet的功能:

    1) 在使用conn的createStatement、prepareStatment时可以开启ResultSet的功能,毕竟ResultSet是从属于Connection的;

    2) 这两个方法的重载版本:

         i. PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency);

         ii. Statement createStatement(int resultSetType, int resultSetConcurrency);

    3) resultSetType用于开启滚动和敏感功能,resultSetConcurrency用于开启并发功能;

    4) 这些功能在ResultSet中定义了静态常量:

滚动/敏感:TYPE_FORWARD_ONLY(不可滚动,即什么功能都不开启,JDK1.4之前是默认的)、TYPE_SCROLL_INSENSITIVE(滚动但不敏感,现在默认的)、TYPE_SCROLL_SENSITIVE(滚动且敏感)

并发:CONCUR_READ_ONLY(只读并发,默认的)、CONCUR_UPDATABLE(可更新并发,开启后就可以通过修改ResultSet中的内容来达到修改数据库中数据的目的了);

!!注意:TYPE_SCROLL_INSENTIVE和TYPE_SCROLL_SENSITIVE需要数据库驱动的支持,对于大多数数据库这两种开关作用上没有区别(MySQL)就是,默认是敏感的!

    5) 使用可更新功能的前提!!!

         i. 必须查询得到的所有数据都来自同一张表;

         ii. 所选数据集中必须包含主键列;

!!两者缺一不可,这是JDBC的实现上的局限性,如果有任意一个规则不符合就会拒绝修改直接抛出异常;


3. 如何通过ResultSet更新数据库中的数据?

    1) 当然首先必须开启并发更新的功能;

    2) 更新分两步,第一步是修改ResultSet中的值(只是该对象中的值),然后再提交更新(将ResultSet中数据的修改以SQL语句形式提交给数据库实现真正的更新);

    3) 首先必须要把记录指针定位到要更新的记录位置处;

    4) 接着调用ResultSet的updateXxx方法修改ResultSet对象中值:两个版本,用列名和索引(从1计)来定位要修改的列

         i. void ResultSet.updateXxx(int columnIndex, Xxx x);

         ii. void ResultSet.updateXxx(String columnLabel, Xxx x);

    5) 最后将修改提交实现真正的更新,调用updateRow方法即可(即将修改后的行更新到真实数据库的表中):void ResultSet.updateRow();

!!实际上它会把这种修改转化成SQL语句提交给数据库执行(以为数据库只认识SQL查询);


4. 示例:可滚动、可更新的结果集

public class Test {

	private String driver;
	private String url;
	private String user;
	private String pass;
	
	public void init() throws Exception {
		Properties props = new Properties();
		props.load(new FileInputStream("mysql.ini"));
		driver = props.getProperty("driver");
		url = props.getProperty("url");
		user = props.getProperty("user");
		pass = props.getProperty("pass");
		
		try (
			Connection conn = DriverManager.getConnection(url, user, pass);
			PreparedStatement pstmt = conn.prepareStatement("select * from student_table", 
					ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); // 可滚动可更新
			ResultSet rs = pstmt.executeQuery();
		) {
			rs.afterLast(); // 可滚动
			int i = 0;
			while (rs.previous()) { // 按照逆序修改
				rs.updateString(2, "Peter" + i++);
				rs.updateRow();
			}
		}
	}

	public static void main(String[] args) throws Exception {
		new Test().init();
	}

}
!!运行后可以看到数据可表中的名字都变成了Peter + i了,并且i是逆序的;

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页