jdbc ResultSetType 说明

JDBC1.0 、JDBC2.0 、JDBC3.0 中分别用以下方法创建Statement 。 
JDBC1.0 : createStatement() 
JDBC2.0 : createStatement(resultSetType, resultSetConcurrency) 
JDBC3.0 : createStatement(resultSetType, resultSetConcurrency, resultSetHoldability)

下面依次分析resultSetType 、resultSetConcurrency 、resultSetHoldability 这几个参数的含义。

一 ResultSetType

      resultSetType 的可选值有: ResultSet.TYPE_FORWARD_ONLY 、ResultSet.TYPE_SCROLL_INSENSITIVEResultSet.TYPE_SCROLL_SENSITIVE 。

ResultSet.TYPE_FORWARD_ONLY

默认的cursor 类型,仅仅支持结果集forward ,不支持backforward ,random ,last ,first 等操作。  

ResultSet.TYPE_SCROLL_INSENSITIVE

支持结果集backforward ,random ,last ,first 等操作,对其它session 对数据库中数据做出的更改是不敏感的。

实现方法:从数据库取出数据后,会把全部数据缓存到cache 中,对结果集的后续操作,是操作的cache 中的数据,数据库中记录发生变化后,不影响cache 中的数据,所以ResultSet 对结果集中的数据是INSENSITIVE 的。

ResultSet.TYPE_SCROLL_SENSITIVE

支持结果集backforward ,random ,last ,first 等操作,对其它session 对数据库中数据做出的更改是敏感的,即其他session 修改了数据库中的数据,会反应到本结果集中。

实现方法:从数据库取出数据后,不是把全部数据缓存到cache 中,而是把每条数据的rowid 缓存到cache 中,对结果集后续操作时,是根据rowid 再去数据库中取数据。所以数据库中记录发生变化后,通过ResultSet 取出的记录是最新的,即ResultSet 是SENSITIVE 的。但insert 和delete 操作不会影响到ResultSet ,因为insert 数据的rowid 不在ResultSet 取出的rowid 中,所以insert 的数据对ResultSet 是不可见的,而delete 数据的rowid 依旧在ResultSet 中,所以ResultSet 仍可以取出被删除的记录( 因为一般数据库的删除是标记删除,不是真正在数据库文件中删除 )。

做个试验,验证一下SENSITIVE 特性。数据库为oracle10g ,驱动为ojdbc14.jar 。

test 表中数据如下:

c1c2c3
1c11c21c3
2c12c22c3
3c13c23c3

程序如下:

public static void testResultSetSensitive(Connection conn) throws Exception{
String sql = "SELECT c1,c2,c3 FROM test";
	try {
	Statement stmt =
       conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
			
	ResultSet rs = stmt.executeQuery(sql);
			
	while (rs.next()) {
	 System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString(1) + "\t" + rs.getString(2)
		+ "\t" + rs.getString(3));
	  Thread.sleep(20000);
	}
			
	rs.close();
	stmt.close();
	} catch (SQLException e) {
		e.printStackTrace();
	} finally {
	 try {
		conn.close();
	} catch (Exception e) {
		}
	}
}
        

定义ResultSet 为 ResultSet. TYPE_SCROLL_SENSITIVE 类型,首先执行 sql 访问数据库,然后执行 rs.next() 移动游标取数据。在循环里面加上 Thread.sleep (20000) 的目的是为了我们有时间在后台把数据库里的数据改了。比如当在循环里打印出第一行的数据后,我们在后台,把第三行数据的 c3 列改成 ”3uuu” 。如果 ResultSet 真的是敏感的话,那应该取出 ”3uuu” ,而不是原始的“ 3c 3 ”。但最终的结果却是如下:

[ 行号: 1] 1c1   1c2   1c3
[ 行号: 2] 2c1   2c2   2c3
[ 行号: 3] 3c1   3c2   3c3

数据没变呀,ResultSet 不敏感啊!于是去查阅资料,找了n 久,还是在英文文档上找到了答案。原来是fetchsize 的问题。调用ResultSet 的next 方法取数据时,并不是每调用一次方法就去数据库里查一次,而是有个fetchSize, 一次取fetchSize 条数据。Oracle 默认的fetchsize 等于10 ,所以上面的代码在第一次调用rs.next() 时,就已经把3 条数据都取出来了,所以才会有上面的结果。

      第二次实验,在ResultSet rs = stmt.executeQuery(sql); 前面加上 stmt.setFetchSize(1); 将fetchSize 设置为1 。然后重新第一次实验的步骤,发现最 终结果为:

[ 行号: 1] 1c1   1c2   1c3

[ 行号: 2] 2c1   2c2   2c3

[ 行号: 3] 3c1   3c2   3uuu

    原因就是 fetchsize 设置为 1 时,每次 next 取数时都会重新用 rowid 取数据库里取数据,当然取到的是最新的数据了。

      二 ResultSetConcurrency

      ResultSetConcurrency的可选值有2个:
      ResultSet.CONCUR_READ_ONLY 在ResultSet中的数据记录是只读的,不可以修改
      ResultSet.CONCUR_UPDATABLE 在ResultSet中的数据记录可以任意修改,然后更新到数据库,可以插入,删除,修改。

      三 ResultSetHoldability
   ResultSetHoldability 的可选值有2 个 :

     HOLD_CURSORS_OVER_COMMIT: 在事务commit 或rollback 后,ResultSet 仍然可用。 
     CLOSE_CURSORS_AT_COMMIT: 
在事务commit 或rollback 后,ResultSet 被关闭。

     需要注意的地方:

   1 :Oracle 只支持HOLD_CURSORS_OVER_COMMIT 。

   2 :当Statement 执行下一个查询,生成第二个ResultSet 时,第一个ResultSet 会被关闭,这和是否支持支持HOLD_CURSORS_OVER_COMMIT 无关。

     四 验证数据库是否支持ResultSet的各种特性

不同的数据库版本及 JDBC 驱动版本,对 ResultSet 的各种高级特性的支持是不一样的,我们可以通过以下方法,来验证具体的数据库及 JDBC 驱动,是否支持 ResultSet 的各种特性。

     DatabaseMetaData dbMeta = conn.getMetaData();

      然后调用 DatabaseMetaData 对象的以下方法:

       boolean supportsResultSetType(int resultSetType);

       boolean supportsResultSetConcurrency(int type, int concurrency);

       boolean supportsResultSetHoldability(int holdability);

 

转自 http://www.java3z.com/cwbwebhome/article/article8/828.html?id=2244

<think>好的,我需要详细说明cppconn中prepareStatement的多个重载函数。首先,我得确认用户指的是哪个库。通常,cppconn指的是MySQL Connector/C++中的一部分,用于数据库操作。接下来,用户提到的prepareStatement应该是sql::Connection接口中的方法,用于创建预编译语句对象。 根据MySQL Connector/C++的文档,sql::Connection接口的prepareStatement方法确实有多个重载。我需要回忆或查找这些重载的具体形式。常见的重载可能涉及不同的参数,比如是否传递字符集或编码信息,或者处理不同参数数量的情况。 首先,标准的prepareStatement方法接受一个SQL查询字符串作为参数,返回一个sql::PreparedStatement指针。例如: ```cpp sql::PreparedStatement *prepareStatement(const sql::SQLString& sql); ``` 这是最常用的重载,用户传入SQL语句,如"INSERT INTO table VALUES (?, ?)",然后使用预编译语句绑定参数。 另一个可能的变体是支持字符集或编码的设置。例如: ```cpp sql::PreparedStatement *prepareStatement(const sql::SQLString& sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability); ``` 这里的参数可能控制结果集的类型(如只向前或可滚动)、并发方式(只读或可更新)以及结果集的可保持性。这些参数对应JDBC中的类似选项,可能用于更精细的控制。 还可能存在其他重载,比如接受额外的选项参数或标志,但根据文档,可能主要的两个重载是上述两种。需要确认是否存在更多版本,或者是否某些参数有默认值导致函数重载。 另外,要注意异常处理,prepareStatement可能抛出sql::SQLException,所以使用时需要try-catch块。 现在需要组织这些信息,确保结构清晰,分点说明每个重载的参数、用途和示例。同时,提醒用户注意资源管理和异常处理,比如使用智能指针来管理返回的PreparedStatement指针,防止内存泄漏。 可能还需要比较不同重载的应用场景,例如,当需要处理可滚动的结果集时,使用第二个重载,指定resultSetType为sql::ResultSet::TYPE_SCROLL_INSENSITIVE等。 最后,确保所有代码示例正确使用$$...$$格式,行内代码用$...$,符合用户给定的格式要求。</think>在 MySQL Connector/C++ 中,`sql::Connection` 接口的 `prepareStatement` 方法用于创建预编译语句对象。其重载函数及详细说明如下: --- ### 1. 基础重载(最常用) $$ sql::PreparedStatement* prepareStatement(const sql::SQLString& sql) $$ - **参数**: - `sql`: 预编译的 SQL 语句字符串,使用 `?` 占位符(例如 `"INSERT INTO table (col1, col2) VALUES (?, ?)"`)。 - **返回值**:指向 `sql::PreparedStatement` 对象的指针。 - **用途**:创建标准预编译语句,适用于大多数 SQL 操作。 - **示例**: ```cpp sql::Connection *con = driver->connect("tcp://127.0.0.1:3306", "user", "pass"); sql::PreparedStatement *pstmt = con->prepareStatement("SELECT * FROM users WHERE id = ?"); pstmt->setInt(1, 1001); // 绑定参数 sql::ResultSet *res = pstmt->executeQuery(); ``` --- ### 2. 高级控制重载(结果集配置) $$ sql::PreparedStatement* prepareStatement( const sql::SQLString& sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability ) $$ - **参数**: - `sql`: SQL 语句字符串。 - `resultSetType`: 结果集类型,控制游标行为: - `sql::ResultSet::TYPE_FORWARD_ONLY`(默认,只向前遍历) - `sql::ResultSet::TYPE_SCROLL_INSENSITIVE`(可滚动,不感知外部修改) - `sql::ResultSet::TYPE_SCROLL_SENSITIVE`(可滚动,感知外部修改,实际可能不生效)。 - `resultSetConcurrency`: 并发模式: - `sql::ResultSet::CONCUR_READ_ONLY`(默认,只读) - `sql::ResultSet::CONCUR_UPDATABLE`(可更新结果集,需数据库支持)。 - `resultSetHoldability`: 结果集保持性(通常用 `0` 或默认值)。 - **用途**:精细控制结果集行为,适用于复杂查询场景。 - **示例**: ```cpp sql::PreparedStatement *pstmt = con->prepareStatement( "SELECT * FROM orders WHERE amount > ?", sql::ResultSet::TYPE_SCROLL_INSENSITIVE, sql::ResultSet::CONCUR_READ_ONLY, 0 ); ``` --- ### 3. 其他注意事项 1. **资源管理**: - 需手动释放 `PreparedStatement` 对象: ```cpp delete pstmt; // 使用后释放内存 ``` - 建议使用智能指针(如 `std::unique_ptr`)避免内存泄漏: ```cpp std::unique_ptr<sql::PreparedStatement> pstmt(con->prepareStatement("...")); ``` 2. **异常处理**: - 所有重载可能抛出 `sql::SQLException`,需捕获异常: ```cpp try { pstmt = con->prepareStatement("..."); } catch (sql::SQLException &e) { std::cerr << "SQL Error: " << e.what() << std::endl; } ``` 3. **占位符规则**: - 使用 `?` 作为参数占位符。 - 绑定参数时按顺序从 `1` 开始(例如 `pstmt->setString(1, "value")`)。 --- ### 4. 应用场景对比 | 重载类型 | 适用场景 | 性能影响 | |------------------|----------------------------------|----------------| | 基础重载 | 简单查询、插入、更新、删除 | 低开销 | | 高级控制重载 | 需要可滚动或可更新的结果集 | 可能增加开销 | 建议优先使用基础重载,仅在需要高级功能时选择高级重载。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值