首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

JDBC处理大结果集

2023-11-12 来源:花图问答

一.背景说明

之前在处理一个优化task时接触到了Jdbc对于大结果集的处理相关内容,记录下。问题开始于前置机抽数程序在抽取大数据量数据时出现卡死的情况。数据源方面客户使用的是Oracle数据库,使用Jdbc直接连接数据库。根据字段数量及类型不同,大概在单个接口数据量达到10万~15万左右就会出现卡死。

二.原因探寻

猜测一:一开始以为是因为写入的csv文件对大小及记录数有限制,因为每次大概都是写到70多M的时候就会卡死,而且比如xls文件的根据office版本不同确实是有限制的。但经过网上搜索及实际验证后发现,并不是因为这个原因。不过这个地方还是可以找到可以优化的点,就是按大小或记录数分批写文件,当行数真的有要求时可以类似于这样做:while ( rs.next() ) /* 此处处理业务逻辑 */{count++;if ( count % pageSize == 0 ){System.out.println( " 写入到第 " + (count/pageSize) + " 个文件中!" );

}

}

猜测二:这个时候又在想应该一次性处理的结果集太大导致无法处理,哪我们能不能试试把结果集分割下,或者使一次处理的结果集尽量小点呢?由此,研究了下分页查询的用法,Oracle里暂时还不能用limit,所以是借助伪列rownum来实现的,如下:"select * from (select rownum as rowno,ai.* " +"from ai, " +" mv, " +"hscf.hscf_approved_ou_vendors haov, "+"hscf.hscf_apr_ou_vdr_sync_timestamp haov_ts "+"where ai.view_id = mv.mv_id " +" " +"and ai.org_id = haov.operating_unit_id " +"and mv.vendor_id = haov.vendor_id " +"and ? = haov.interface_entity_code " +"and ‘Y‘ = haov.enabled_flag " +"and haov.interface_entity_code = haov_ts.interface_entity_code " +"and haov.operating_unit_id = haov_ts.operating_unit_id " +"and haov.vendor_id = haov_ts.vendor_id "+"and rownum <= * ) " +"where rowno > ( -1) * " ;

但是这个用上之后,发现其实并不能解决问题。甚至就总的效率而言,反而是下降了。因为每次找到分页的起始点其实也是会花费时间的,页数越往后时间花的越多。由此可以记录一下:分页并不适用于提高总的效率。只是有些时候我们不需要获取所有记录,只是想查看一部分的时候,比如前端的页面展示。实际上,因为我们这里为了提高查询效率使用了物化视图,该建的索引都建了,去掉了不必要的Order by,还使用了PARALLEL特性。所以到这里可以发现问题的关键并不在于磁盘IO,SQL效率上,应该从别的角度去考虑。

猜测三:上面的方法虽然并没有实际解决问题,但其实还是提供了一些有用的想法,且让我有所收获的。到这里其实我们应该冷静下来,好好去理一下思路,可以知道重点其实应该在结果集上,所以我们应该好好的研究下ResultSet这个类的各个属性方法。由此,我获得了一些有用的信息,并最终结局了问题。Jdbc只是接口规范,实际的实现还在于驱动类,说这句话的目的在于提醒,解决这种问题一定要具体到数据库类型。比如,网上说使用setFetchSize修改每次提取的记录数可以解决Jdbc大数据量抽取效率的问题,但我看了下人家用的是Mysql。而在我的这个案例里,数据库用的Oracle,每次默认的fetchSize为10,而这个其实是有Oracle给出的一个比较合理的大小。因为,一次发送的太多,每次花费在网络传输上的时间也会变多。经过反复查找,终于发现问题的关键在于这里://modified by zhuqingxin at 2018-09-05 for large data extract //pst = getConnection().prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);pst = getConnection().prepareStatement( sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY );//modified by zhuqingxin at 2018-09-05 for large data extract 原来的那种结果集设置不合理,导致JVM会把结果集主要存储于内存中,而系统分配给JVM的内存应该是有限制的。当数据量很大的时候,自然就会出问题。后面那种设置按我理解,应该就是主要把结果集存储于磁盘,到需要的时候再取了。这个优化修改,总共200多M的数据文件大概15分钟全部处理完成并发送到服务器。所以,我之前做的那些分批写文件,后台分页查询,把文件改成文件列表之类的其实都没什么用。解决问题的关键其实就一句话。

三.参考

https://www.cnblogs.com/jay763190097/p/6813792.htmlhttps://www.cnblogs.com/anee/archive/2011/12/20/2675796.htmlhttps://blog.csdn.net/IT_xiaocao/article/details/64920381?locationNum=2&fps=1https://blog.csdn.net/seven_3306/article/details/9303979https://blog.csdn.net/seven_3306/article/details/9303879https://www.cnblogs.com/bukudekong/archive/2011/06/22/2086528.htmlhttps://blog.csdn.net/ooad/article/details/3317705https://wenku.baidu.com/view/72207982fab069dc502201c3.htmlhttps://www.cnblogs.com/zhangzhxb/p/6336484.htm

JDBC处理大结果集

标签:一句话   HERE   timestamp   一个   ooad   where   也会   比较   flag   

小编还为您整理了以下内容,可能对您也有帮助:

JDBC处理数据库查询结果集使用哪些类?

一般对数据插入、更新、删除,使用Statement类。

对数据检索查询使用ResultSet。

JDBC的结果集问

ResultSet 包含符合 SQL 语句中条件的所有行,并且它通过一套 get 方法(这些 get 方法可以访问当前行中的不同列)提供了对这些行中数据的访问。ResultSet.next 方法用于移动到 ResultSet 中的下一行,使下一行成为当前行。

结果集一般是一个表,其中有查询所返回的列标题及相应的值。例如,如果查询为 SELECT a, b, c FROM Table1,则结果集将具有如下形式:

a b c
-------- --------- --------
12345 Cupertino CA
83472 Redmond WA
83492 Boston MA

下面的代码段是执行 SQL 语句的示例。该 SQL 语句将返回行集合,其中列 1 为 int,列 2 为 String,而列 3 则为字节数组:

java.sql.Statement stmt = conn.createStatement();
ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (r.next())
{
// 打印当前行的值。
int i = r.getInt("a");
String s = r.getString("b");
float f = r.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}

5.1.1 行和光标
ResultSet 维护指向其当前数据行的光标。每调用一次 next 方法,光标向下移动一行。最初它位于第一行之前,因此第一次调用 next 将把光标置于第一行上,使它成为当前行。随着每次调用 next 导致光标向下移动一行,按照从上至下的次序获取 ResultSet 行。

在 ResultSet 对象或其父辈 Statement 对象关闭之前,光标一直保持有效。

在 SQL 中,结果表的光标是有名字的。如果数据库允许定位更新或定位删除,则需要将光标的名字作为参数提供给更新或删除命令。可通过调用方法 getCursorName 获得光标名。

注意:不是所有的 DBMS 都支持定位更新和删除。可使用 DatabaseMetaData.supportsPositionedDelete 和 supportsPositionedUpdate 方法来检查特定连接是否支持这些操作。当支持这些操作时,DBMS/驱动程序必须确保适当锁定选定行,以使定位更新不会导致更新异常或其它并发问题。

5.1.2 列
方法 getXXX 提供了获取当前行中某列值的途径。在每一行内,可按任何次序获取列值。但为了保证可移植性,应该从左至右获取列值,并且一次性地读取列值。

列名或列号可用于标识要从中获取数据的列。例如,如果 ResultSet 对象 rs 的第二列名为“title”,并将值存储为字符串,则下列任一代码将获取存储在该列中的值:

String s = rs.getString("title");
String s = rs.getString(2);

注意列是从左至右编号的,并且从列 1 开始。同时,用作 getXXX 方法的输入的列名不区分大小写。

提供使用列名这个选项的目的是为了让在查询中指定列名的用户可使用相同的名字作为 getXXX 方法的参数。另一方面,如果 select 语句未指定列名(例如在“select * from table1”中或列是导出的时),则应该使用列号。这些情况下,用户将无法确切知道列名。

有些情况下,SQL 查询返回的结果集中可能有多个列具有相同的名字。如果列名用作 getXXX 方法的参数,则 getXXX 将返回第一个匹配列名的值。因而,如果多个列具有相同的名字,则需要使用列索引来确保检索了正确的列值。这时,使用列号效率要稍微高一些。

关于 ResultSet 中列的信息,可通过调用方法 ResultSet.getMetaData 得到。返回的 ResultSetMetaData 对象将给出其 ResultSet 对象各列的编号、类型和属性。

如果列名已知,但不知其索引,则可用方法 findColumn 得到其列号。

JDBC的结果集问

ResultSet 包含符合 SQL 语句中条件的所有行,并且它通过一套 get 方法(这些 get 方法可以访问当前行中的不同列)提供了对这些行中数据的访问。ResultSet.next 方法用于移动到 ResultSet 中的下一行,使下一行成为当前行。

结果集一般是一个表,其中有查询所返回的列标题及相应的值。例如,如果查询为 SELECT a, b, c FROM Table1,则结果集将具有如下形式:

a b c
-------- --------- --------
12345 Cupertino CA
83472 Redmond WA
83492 Boston MA

下面的代码段是执行 SQL 语句的示例。该 SQL 语句将返回行集合,其中列 1 为 int,列 2 为 String,而列 3 则为字节数组:

java.sql.Statement stmt = conn.createStatement();
ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (r.next())
{
// 打印当前行的值。
int i = r.getInt("a");
String s = r.getString("b");
float f = r.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}

5.1.1 行和光标
ResultSet 维护指向其当前数据行的光标。每调用一次 next 方法,光标向下移动一行。最初它位于第一行之前,因此第一次调用 next 将把光标置于第一行上,使它成为当前行。随着每次调用 next 导致光标向下移动一行,按照从上至下的次序获取 ResultSet 行。

在 ResultSet 对象或其父辈 Statement 对象关闭之前,光标一直保持有效。

在 SQL 中,结果表的光标是有名字的。如果数据库允许定位更新或定位删除,则需要将光标的名字作为参数提供给更新或删除命令。可通过调用方法 getCursorName 获得光标名。

注意:不是所有的 DBMS 都支持定位更新和删除。可使用 DatabaseMetaData.supportsPositionedDelete 和 supportsPositionedUpdate 方法来检查特定连接是否支持这些操作。当支持这些操作时,DBMS/驱动程序必须确保适当锁定选定行,以使定位更新不会导致更新异常或其它并发问题。

5.1.2 列
方法 getXXX 提供了获取当前行中某列值的途径。在每一行内,可按任何次序获取列值。但为了保证可移植性,应该从左至右获取列值,并且一次性地读取列值。

列名或列号可用于标识要从中获取数据的列。例如,如果 ResultSet 对象 rs 的第二列名为“title”,并将值存储为字符串,则下列任一代码将获取存储在该列中的值:

String s = rs.getString("title");
String s = rs.getString(2);

注意列是从左至右编号的,并且从列 1 开始。同时,用作 getXXX 方法的输入的列名不区分大小写。

提供使用列名这个选项的目的是为了让在查询中指定列名的用户可使用相同的名字作为 getXXX 方法的参数。另一方面,如果 select 语句未指定列名(例如在“select * from table1”中或列是导出的时),则应该使用列号。这些情况下,用户将无法确切知道列名。

有些情况下,SQL 查询返回的结果集中可能有多个列具有相同的名字。如果列名用作 getXXX 方法的参数,则 getXXX 将返回第一个匹配列名的值。因而,如果多个列具有相同的名字,则需要使用列索引来确保检索了正确的列值。这时,使用列号效率要稍微高一些。

关于 ResultSet 中列的信息,可通过调用方法 ResultSet.getMetaData 得到。返回的 ResultSetMetaData 对象将给出其 ResultSet 对象各列的编号、类型和属性。

如果列名已知,但不知其索引,则可用方法 findColumn 得到其列号。

JDBC中的几种结果集ResultSet,RowSet求解

获得可滚动的结果集:

Statement stat = conn.createStatement(

ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);获得可更新的结果集:

Statement stat = conn.createStatement(

ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATE);ResultSet中的Type取值:

TYPE_FORWARD_ONLY 不可滚动

TYPE_SCROLL_INSENSITIVE 结果集可滚动,但对数据库变化不敏感

TYPE_SCROLL_SENSITIVE 结果集可滚动,但对数据库变化敏感

ResultSet中的Concurrency取值:

CONCUR_READ_ONLY 结果集不能用于更新数据库

CONCUR_UPDATEABLE 结果集可以用于更新数据库

元数据的概念

通过java.sql.DatabaseMetaData可以获取数据库结构和表的详细信息。

可滚动的结果集虽然强,但交换过程,必须始终与数据库保持连接。如果一个操作要持续很久,则占用了宝贵的数据库连接资源。这时可以考虑使用行集,即RowSet。

RowSet继承自ResultSet,但不必始终保持与数据库的连接。

如何利用JDBC发送SQL语句,并取回多个结果集

step1:构造连接
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db","root","123");

step2:构造语句
String sql = "select username,password from t_user where username=?";
PreparedStatement stmt = con.prepareStatement(sql);
stmt.setString(1, "zhangshan"); //给SQL的"?"(问号)传值。

step3:执行查询
ResultSet rs = stmt.executeQuery(); //rs就是SQL查询语句返回的结果集

step4:处理结果(java 获取SQL查询语句返回的结果)
List list = new ArrayList();
//遍历结果集,这样写就可以了,就是一个循环,有多少条记录,这里就会循环多少次,
//一次就是一条记录,想像一下就像一个表的一条记录
//在这里可以做查询出来的数据处理,可以封装成对象之类的(就是把值给它)
if(rs.next()) { //遍历结果集,这样写就可以了
User u = new User();
String username = rs.getString("username");
String address = rs.getString("password ");
u.setUsername(username);
u.setAddress(address);
list.add(u);
}
//上面这个例子意思是,把每一条记录封装成了一个User对象,然后这些User对象都放存入到了一个list

step4:关闭连接等

如何利用JDBC发送SQL语句,并取回多个结果集

step1:构造连接
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db","root","123");

step2:构造语句
String sql = "select username,password from t_user where username=?";
PreparedStatement stmt = con.prepareStatement(sql);
stmt.setString(1, "zhangshan"); //给SQL的"?"(问号)传值。

step3:执行查询
ResultSet rs = stmt.executeQuery(); //rs就是SQL查询语句返回的结果集

step4:处理结果(java 获取SQL查询语句返回的结果)
List list = new ArrayList();
//遍历结果集,这样写就可以了,就是一个循环,有多少条记录,这里就会循环多少次,
//一次就是一条记录,想像一下就像一个表的一条记录
//在这里可以做查询出来的数据处理,可以封装成对象之类的(就是把值给它)
if(rs.next()) { //遍历结果集,这样写就可以了
User u = new User();
String username = rs.getString("username");
String address = rs.getString("password ");
u.setUsername(username);
u.setAddress(address);
list.add(u);
}
//上面这个例子意思是,把每一条记录封装成了一个User对象,然后这些User对象都放存入到了一个list

step4:关闭连接等

使用JDBC编程,应如何控制结果集ResultSet的指针,使之能够上下移动,以及...

说明:Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);

通用格式为:Statement stmt=con.createStatement(int type,int concurrency);我们在访问数据库的时候,在读取返回结果的时候,可能要前后移动指针,比如我们先计算有多少条信息,这是我们就需要把指针移到最后来计算,然后再把指针移到最前面,逐条读取,有时我们只需要逐条读取就可以了。还有就是有只我们只需要读取数据,为了不破坏数据,我们可采用只读模式,有时我们需要望数据库里添加记录,这是我们就要采用可更新数据库的模式。下面我们就对其参数进行说明:

参数 int type

ResultSet.TYPE_FORWORD_ONLY 结果集的游标只能向下滚动。

ResultSet.TYPE_SCROLL_INSENSITIVE 结果集的游标可以上下移动,当数据库变化时,当前结果集不变。

ResultSet.TYPE_SCROLL_SENSITIVE 返回可滚动的结果集,当数据库变化时,当前结果集同步改变。

参数 int concurrency

ResultSet.CONCUR_READ_ONLY 不能用结果集更新数据库中的表。

ResultSet.CONCUR_UPDATETABLE 能用结果集更新数据库中的表。

查询语句

ResultSet re=stmt.executeUpdate(SQL语句);用来更新数据库信息或插入数据

ResultSet re=stmt.executeQuery(SQL语句);用来查询数据库信息

当我们使用ResultSet re=stmt.executeQuery(SQL语句)查询后,我们可以使用下列方法获得信息:

public boolean previous() 将游标向上移动,该方法返回boolean型数据,当移到结果集第一行之前时,返回false。

public void beforeFirst 将游标移动到结果集的初始位置,即在第一行之前。

public void afterLast() 将游标移到结果集最后一行之后。

public void first() 将游标移到结果集的第一行。

public void last() 将游标移到结果集的最后一行。

public boolean isAfterLast() 判断游标是否在最后一行之后。

public boolean isBeforeFirst() 判断游标是否在第一行之前。

public boolean ifFirst() 判断游标是否指向结果集的第一行。

public boolean isLast() 判断游标是否指向结果集的最后一行。

public int getRow() 得到当前游标所指向行的行号,行号从1开始,如果结果集没有行,返回0。

public boolean absolute(int row) 将游标移到参数row指定的行号。如果row取负值,就是倒数的行数,absolute(-1)表示移到最后一行,absolute(-2)表示移到倒数第2行。当移动到第一行前面或最后一行的后面时,该方法返回false
说明:Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);

通用格式为:Statement stmt=con.createStatement(int type,int concurrency);我们在访问数据库的时候,在读取返回结果的时候,可能要前后移动指针,比如我们先计算有多少条信息,这是我们就需要把指针移到最后来计算,然后再把指针移到最前面,逐条读取,有时我们只需要逐条读取就可以了。还有就是有只我们只需要读取数据,为了不破坏数据,我们可采用只读模式,有时我们需要望数据库里添加记录,这是我们就要采用可更新数据库的模式。下面我们就对其参数进行说明:

参数 int type

ResultSet.TYPE_FORWORD_ONLY 结果集的游标只能向下滚动。

ResultSet.TYPE_SCROLL_INSENSITIVE 结果集的游标可以上下移动,当数据库变化时,当前结果集不变。

ResultSet.TYPE_SCROLL_SENSITIVE 返回可滚动的结果集,当数据库变化时,当前结果集同步改变。

参数 int concurrency

ResultSet.CONCUR_READ_ONLY 不能用结果集更新数据库中的表。

ResultSet.CONCUR_UPDATETABLE 能用结果集更新数据库中的表。

查询语句

ResultSet re=stmt.executeUpdate(SQL语句);用来更新数据库信息或插入数据

ResultSet re=stmt.executeQuery(SQL语句);用来查询数据库信息

当我们使用ResultSet re=stmt.executeQuery(SQL语句)查询后,我们可以使用下列方法获得信息:

public boolean previous() 将游标向上移动,该方法返回boolean型数据,当移到结果集第一行之前时,返回false。

public void beforeFirst 将游标移动到结果集的初始位置,即在第一行之前。

public void afterLast() 将游标移到结果集最后一行之后。

public void first() 将游标移到结果集的第一行。

public void last() 将游标移到结果集的最后一行。

public boolean isAfterLast() 判断游标是否在最后一行之后。

public boolean isBeforeFirst() 判断游标是否在第一行之前。

public boolean ifFirst() 判断游标是否指向结果集的第一行。

public boolean isLast() 判断游标是否指向结果集的最后一行。

public int getRow() 得到当前游标所指向行的行号,行号从1开始,如果结果集没有行,返回0。

public boolean absolute(int row) 将游标移到参数row指定的行号。如果row取负值,就是倒数的行数,absolute(-1)表示移到最后一行,absolute(-2)表示移到倒数第2行。当移动到第一行前面或最后一行的后面时,该方法返回false

参考资料:http://eternal1025.javaeye.com/blog/342573

使用JDBC编程,应如何控制结果集ResultSet的指针,使之能够上下移动,以及...

说明:Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);

通用格式为:Statement stmt=con.createStatement(int type,int concurrency);我们在访问数据库的时候,在读取返回结果的时候,可能要前后移动指针,比如我们先计算有多少条信息,这是我们就需要把指针移到最后来计算,然后再把指针移到最前面,逐条读取,有时我们只需要逐条读取就可以了。还有就是有只我们只需要读取数据,为了不破坏数据,我们可采用只读模式,有时我们需要望数据库里添加记录,这是我们就要采用可更新数据库的模式。下面我们就对其参数进行说明:

参数 int type

ResultSet.TYPE_FORWORD_ONLY 结果集的游标只能向下滚动。

ResultSet.TYPE_SCROLL_INSENSITIVE 结果集的游标可以上下移动,当数据库变化时,当前结果集不变。

ResultSet.TYPE_SCROLL_SENSITIVE 返回可滚动的结果集,当数据库变化时,当前结果集同步改变。

参数 int concurrency

ResultSet.CONCUR_READ_ONLY 不能用结果集更新数据库中的表。

ResultSet.CONCUR_UPDATETABLE 能用结果集更新数据库中的表。

查询语句

ResultSet re=stmt.executeUpdate(SQL语句);用来更新数据库信息或插入数据

ResultSet re=stmt.executeQuery(SQL语句);用来查询数据库信息

当我们使用ResultSet re=stmt.executeQuery(SQL语句)查询后,我们可以使用下列方法获得信息:

public boolean previous() 将游标向上移动,该方法返回boolean型数据,当移到结果集第一行之前时,返回false。

public void beforeFirst 将游标移动到结果集的初始位置,即在第一行之前。

public void afterLast() 将游标移到结果集最后一行之后。

public void first() 将游标移到结果集的第一行。

public void last() 将游标移到结果集的最后一行。

public boolean isAfterLast() 判断游标是否在最后一行之后。

public boolean isBeforeFirst() 判断游标是否在第一行之前。

public boolean ifFirst() 判断游标是否指向结果集的第一行。

public boolean isLast() 判断游标是否指向结果集的最后一行。

public int getRow() 得到当前游标所指向行的行号,行号从1开始,如果结果集没有行,返回0。

public boolean absolute(int row) 将游标移到参数row指定的行号。如果row取负值,就是倒数的行数,absolute(-1)表示移到最后一行,absolute(-2)表示移到倒数第2行。当移动到第一行前面或最后一行的后面时,该方法返回false
说明:Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);

通用格式为:Statement stmt=con.createStatement(int type,int concurrency);我们在访问数据库的时候,在读取返回结果的时候,可能要前后移动指针,比如我们先计算有多少条信息,这是我们就需要把指针移到最后来计算,然后再把指针移到最前面,逐条读取,有时我们只需要逐条读取就可以了。还有就是有只我们只需要读取数据,为了不破坏数据,我们可采用只读模式,有时我们需要望数据库里添加记录,这是我们就要采用可更新数据库的模式。下面我们就对其参数进行说明:

参数 int type

ResultSet.TYPE_FORWORD_ONLY 结果集的游标只能向下滚动。

ResultSet.TYPE_SCROLL_INSENSITIVE 结果集的游标可以上下移动,当数据库变化时,当前结果集不变。

ResultSet.TYPE_SCROLL_SENSITIVE 返回可滚动的结果集,当数据库变化时,当前结果集同步改变。

参数 int concurrency

ResultSet.CONCUR_READ_ONLY 不能用结果集更新数据库中的表。

ResultSet.CONCUR_UPDATETABLE 能用结果集更新数据库中的表。

查询语句

ResultSet re=stmt.executeUpdate(SQL语句);用来更新数据库信息或插入数据

ResultSet re=stmt.executeQuery(SQL语句);用来查询数据库信息

当我们使用ResultSet re=stmt.executeQuery(SQL语句)查询后,我们可以使用下列方法获得信息:

public boolean previous() 将游标向上移动,该方法返回boolean型数据,当移到结果集第一行之前时,返回false。

public void beforeFirst 将游标移动到结果集的初始位置,即在第一行之前。

public void afterLast() 将游标移到结果集最后一行之后。

public void first() 将游标移到结果集的第一行。

public void last() 将游标移到结果集的最后一行。

public boolean isAfterLast() 判断游标是否在最后一行之后。

public boolean isBeforeFirst() 判断游标是否在第一行之前。

public boolean ifFirst() 判断游标是否指向结果集的第一行。

public boolean isLast() 判断游标是否指向结果集的最后一行。

public int getRow() 得到当前游标所指向行的行号,行号从1开始,如果结果集没有行,返回0。

public boolean absolute(int row) 将游标移到参数row指定的行号。如果row取负值,就是倒数的行数,absolute(-1)表示移到最后一行,absolute(-2)表示移到倒数第2行。当移动到第一行前面或最后一行的后面时,该方法返回false

参考资料:http://eternal1025.javaeye.com/blog/342573

jdbc模板占位符替换,处理结果集使用什么机制

package com.hanchao.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
* jdbc学习总结二
* @author hanlw
* 2012-07-09
*/
public class TestJdbcNew {

/**
* 上一篇文章,我们对JDBC有了初步的了解,并且知道了如何使用JDBC了。
* 但是,那只是JDBC的了解性操作实例。实际开发中,我们是不能那么玩的!!
*
* ★下面我们学习一下:JDBC的占位符的使用,以后写程序建议都要这么玩的!!
*
* 注意事项:我们的异常应该捕获;而不是抛出来啊!!
*
* SQLException是非运行时异常,必须要捕获或者向上抛出!!★
*/

public static void main(String[] args) throws Exception {
/**
* 1.jdbc对Mysql的insert操作
*/
// insert("cherry","shanghai");

/**
* 2.jdbc对mysql的update操作
*/
// update("update",12);

/**
* 3.jdbc对mysql的delete操作
*/
// delete(12);

/**
* 4.jdbc对mysql的retrieve 操作
*/
retrieve(15);
}

/**
* jdbc对mysql的insert操作
*
* @param username 用户名
* @param address 地址
*/
public static void insert(String username,String address) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root","root");

//注意下面几行★
String sql = "insert into t_user(username,address) values(?,?)"; //★
PreparedStatement sta = con.prepareStatement(sql);
sta.setString(1, username);
sta.setString(2, address);

int rows = sta.executeUpdate();
if(rows > 0) {
System.out.println("operate successfully!");
}
sta.close();
con.close();
}

/**
* jdbc对mysql的update操作
*
* @param address 地址
* @param id 主键值
* @throws Exception
*/
public static void update(String address,int id) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root","root");

//★注意下面几行代码
String sql = "update t_user set address=? where id=?";
PreparedStatement sta = con.prepareStatement(sql);
sta.setString(1, address);
sta.setInt(2, id);

int rows = sta.executeUpdate();
if(rows > 0) {
System.out.println("operate successfully");
}
sta.close();
con.close();

}

/**
* jdbc对mysql的删除操作
*
* @param id
* @throws Exception
*/
public static void delete(int id) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root","root");

//★注意点
String sql = "delete from t_user where id=?";
PreparedStatement sta = con.prepareStatement(sql);
sta.setInt(1, id);

int rows = sta.executeUpdate();
if(rows > 0) {
System.out.println("operate successfully!!");
}
sta.close();
con.close();
}

/**
* jdbc对mysql的retrieve操作
*
* @param id
* @throws Exception
*/
public static void retrieve(int id) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root","root");

//注意★
String sql = "select id,username,address from t_user where id=?";
PreparedStatement sta = con.prepareStatement(sql);
sta.setInt(1, id);

ResultSet rs = sta.executeQuery();
//注意:当现实一条记录时:while可以换成if。★
if(rs.next()) {
int did = rs.getInt("id");
String username = rs.getString("username");
String address = rs.getString("address");
System.out.println(did + "\t" + username + "\t" + address);
}

rs.close();
sta.close();
con.close();
}

}

jdbc模板占位符替换,处理结果集使用什么机制

package com.hanchao.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
* jdbc学习总结二
* @author hanlw
* 2012-07-09
*/
public class TestJdbcNew {

/**
* 上一篇文章,我们对JDBC有了初步的了解,并且知道了如何使用JDBC了。
* 但是,那只是JDBC的了解性操作实例。实际开发中,我们是不能那么玩的!!
*
* ★下面我们学习一下:JDBC的占位符的使用,以后写程序建议都要这么玩的!!
*
* 注意事项:我们的异常应该捕获;而不是抛出来啊!!
*
* SQLException是非运行时异常,必须要捕获或者向上抛出!!★
*/

public static void main(String[] args) throws Exception {
/**
* 1.jdbc对Mysql的insert操作
*/
// insert("cherry","shanghai");

/**
* 2.jdbc对mysql的update操作
*/
// update("update",12);

/**
* 3.jdbc对mysql的delete操作
*/
// delete(12);

/**
* 4.jdbc对mysql的retrieve 操作
*/
retrieve(15);
}

/**
* jdbc对mysql的insert操作
*
* @param username 用户名
* @param address 地址
*/
public static void insert(String username,String address) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root","root");

//注意下面几行★
String sql = "insert into t_user(username,address) values(?,?)"; //★
PreparedStatement sta = con.prepareStatement(sql);
sta.setString(1, username);
sta.setString(2, address);

int rows = sta.executeUpdate();
if(rows > 0) {
System.out.println("operate successfully!");
}
sta.close();
con.close();
}

/**
* jdbc对mysql的update操作
*
* @param address 地址
* @param id 主键值
* @throws Exception
*/
public static void update(String address,int id) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root","root");

//★注意下面几行代码
String sql = "update t_user set address=? where id=?";
PreparedStatement sta = con.prepareStatement(sql);
sta.setString(1, address);
sta.setInt(2, id);

int rows = sta.executeUpdate();
if(rows > 0) {
System.out.println("operate successfully");
}
sta.close();
con.close();

}

/**
* jdbc对mysql的删除操作
*
* @param id
* @throws Exception
*/
public static void delete(int id) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root","root");

//★注意点
String sql = "delete from t_user where id=?";
PreparedStatement sta = con.prepareStatement(sql);
sta.setInt(1, id);

int rows = sta.executeUpdate();
if(rows > 0) {
System.out.println("operate successfully!!");
}
sta.close();
con.close();
}

/**
* jdbc对mysql的retrieve操作
*
* @param id
* @throws Exception
*/
public static void retrieve(int id) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root","root");

//注意★
String sql = "select id,username,address from t_user where id=?";
PreparedStatement sta = con.prepareStatement(sql);
sta.setInt(1, id);

ResultSet rs = sta.executeQuery();
//注意:当现实一条记录时:while可以换成if。★
if(rs.next()) {
int did = rs.getInt("id");
String username = rs.getString("username");
String address = rs.getString("address");
System.out.println(did + "\t" + username + "\t" + address);
}

rs.close();
sta.close();
con.close();
}

}

在java中JDBC的主要作用是什么和他的组成有哪些?

JDBC是由一系列连接(Connection)、SQL语句(Statement)和结果集(ResultSet)构成的,其主要作用概括起来有如下3个方面:

建立与数据库的连接。

向数据库发起查询请求。

处理数据库返回结果。

JDBC 怎么获取结果集

你先要连接到数据库吧。。
Class.forName("数据库驱动程序");
Connection conn=DriverManager.getConnection("数据库url","数据库名字","数据库密码");
PreparedStatement ps=conn.PreparedStatement(sql);
ResultSet rs=ps.executeQuery();

sql是你的执行语句,rs就是结果集

JDBC 怎么获取结果集

你先要连接到数据库吧。。
Class.forName("数据库驱动程序");
Connection conn=DriverManager.getConnection("数据库url","数据库名字","数据库密码");
PreparedStatement ps=conn.PreparedStatement(sql);
ResultSet rs=ps.executeQuery();

sql是你的执行语句,rs就是结果集

JDBC中查询的返回结果集ResultSet,怎么修改结果集中某一列的值

void updateArray(int columnIndex,

Array x)

throws SQLException

用 java.sql.Array 值更新指定列。更新方法用于更新当前行或插入行中的列值,并不会更新底层数据库;更新数据库要调用

updateRow 或 insertRow 方法。

可以试试 rs_page .updateArray(“test_name”,值);

JDBC访问数据库后得到的ResultSet 以0还是1开始?

1、是从1开始的,但是个人不介意这么写。

2、建议还是直接写字段 。

原因:比如以后添加字段,然后添加到name前面,那么程序就会读不到name了。

JDBC创建步骤:

1、加载JDBC驱动程序:   

在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),   

这通过java.lang.Class类的静态方法forName(String  className)实现。   

例如:   

try{   

//加载MySql的驱动类

Class.forName("com.mysql.jdbc.Driver") ;   

}catch(ClassNotFoundException e){   

System.out.println("找不到驱动程序类 ,加载驱动失败!");   

e.printStackTrace() ;   

}   

成功加载后,会将Driver类的实例注册到DriverManager类中。  

2、提供JDBC连接的URL   

•连接URL定义了连接数据库时的协议、子协议、数据源标识。   

•书写形式:协议:子协议:数据源标识   

协议:在JDBC中总是以jdbc开始   

子协议:是桥连接的驱动程序或是数据库管理系统名称。   

数据源标识:标记找到数据库来源的地址与连接端口。   

例如:(MySql的连接URL)   

jdbc:mysql:   

//localhost:3306/test?useUnicode=true&characterEncoding=gbk ;

useUnicode=true:表示使用Unicode字符集。如果characterEncoding设置为   

gb2312或GBK,本参数必须设置为true 。characterEncoding=gbk:字符编码方式。 

3、创建数据库的连接   

•要连接数据库,需要向java.sql.DriverManager请求并获得Connection对象,   

该对象就代表一个数据库的连接。   

•使用DriverManager的getConnectin(String url , String username ,    

String password )方法传入指定的欲连接的数据库的路径、数据库的用户名和 密码来获得。   

例如:   

//连接MySql数据库,用户名和密码都是root

String url = "jdbc:mysql://localhost:3306/test" ;    

String username = "root" ;   

String password = "root" ;   

try{   

Connection con =    

DriverManager.getConnection(url , username , password ) ;   

}catch(SQLException se){   

System.out.println("数据库连接失败!");   

se.printStackTrace() ;   

}   

4、创建一个Statement   

•要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3

种类型:   

1、执行静态SQL语句。通常通过Statement实例实现。   

2、执行动态SQL语句。通常通过PreparedStatement实例实现。   

3、执行数据库存储过程。通常通过CallableStatement实例实现。   

具体的实现方式:   

Statement stmt = con.createStatement() ;   

PreparedStatement pstmt = con.prepareStatement(sql) ;   

CallableStatement cstmt =    

con.prepareCall("{CALL demoSp(? , ?)}") ;

显示全文