java数据库编程——读写LOB、可滚动和可更新的结果集

1. 读写LOB

  除了数字、字符串和日期之外,许多数据库还可以存储大对象,例如图片或其它数据。在SQL中,二进制大对象称为BLOB,字符型大对象称为CLOB。

  要读取LOB,需要执行SELECT语句,然后在ResultSet上调用getBlob或getClob方法,这样就可以获得Blob或Clob类型的对象。要从Blob中获取二进制数据,可以调用getBytes或getInputStream。例如,如果你有一张保存图书封面图形的表,那么就可以像下面这样获取一张图像:

PreparedStatement stat = conn.prepareStatement("SELECT Cover FROM BookCovers WHERE ISBN=?");
stat.set(1, isbn);
ResultSet result = stat.executeQuery();
if(result.next()){
    Blob coverBlob = result.getBlob(1);
    Image coverImage = ImageIO.read(coverBlob.getBinaryStream());
}

  类似地,如果获取了Clob对象,那么就可以通过调用getSubString或getCharacterStream方法来获取其中的字符数据。

  要将LOB置于数据库中,需要在Connection对象上调用createBlob或createClob,然后获取一个用于该LOB的输出流或写出器,写出数据,并将该对象存储到数据库中。例如,下面展示了如何存储一张图像:

Blob coverBlob = connection.createBlob();
int offset = 0;
OutputStream out = coverBlob.setBinaryStream(offset);
ImageIO.write(coverImage, "PNG", out);
PreparedStatement stat = conn.prepareStatement("INSERT INTO Cover VALUES(?, ?)");
stat.set(1, isbn);
stat.set(2,coverBlob);
stat.executeUpdate();

2. 可滚动和可更新的结果集

  要让ResultSet可以滚动个和更新,必须在创建Statement对象的时候使用下面的方式指定对应的参数:

Statement stmt = conn.createStatement(type, concurrency);

  对于PreparedStatement,使用下面的方式指定参数:

PreparedStatement pstmt = conn.prepareStatement(sql, type, concurrency);

其中,type表示ResuleSet的类型,而concurrency表示是否可以使用ResuleSet来更新数据库。

type和concurrency的取值以及含义如下:

ResultSet类的type值
解释
ResultSet.TYPE_FORWARD_ONLY 结果集不能滚动(默认值)
ResultSet.TYPE_SCROLL_INSENSITIVE 结果集可以滚动,但ResuleSet对数据库中数据变化不敏感
 ResultSet.TYPE_SCROLL_SENSIT  IVE 结果集可以滚动,并且ResuleSet对数据库中发生的改变敏感
ResultSet类的Concurrency值
解释
ResultSet.CONCUR_READ_ONLY 结果集不能用于更新数据库(默认值)
ResultSet.CONCUR_UPDATABLE 结果集可以用于更新数据库

JDBC的结果集有很多类型。这些结果集有不同的特性,以满足各种需要。这在高性能的JDBC数据操作中有着重要应用。下面是一个应用实例:

package lavasoft.common; 

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; 

/**
* JDBC可滚动可更新感知更新结果集测试
*
* @author leizhimin 2009-12-8 20:09:03
*/
public class TestResultSet {
        public static void main(String[] args) {
                testScrollResultSet();
                testUpdateResultSet();
        } 

        /**
         * 可更新结果集更新测试
         */
        public static void testUpdateResultSet() {
                Connection conn = DBToolkit.getConnection();
                String sql = "SELECT * FROM book";
                try {
                        Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
                        ResultSet rs = stmt.executeQuery(sql); 

                        System.out.println("---------原结果集--------");
                        while (rs.next()) {
                                System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3));
                        } 

                        System.out.println("---------插入一条记录--------");
                        rs.first();
                        //将光标移动到插入行上
                        rs.moveToInsertRow();
                        //构建行数据
                        rs.updateString(2, "xxxx");
                        rs.updateString(3, "x");
                        //插入一行
                        rs.insertRow(); 

                        System.out.println("-------------更新一条记录-------------");
                        rs.absolute(3);
                        //构建行数据
                        rs.updateString(2, "uuuu");
                        rs.updateString(3, "u");
                        rs.updateRow(); 

                        System.out.println("---------插入更新后的结果集--------");
                        rs = stmt.executeQuery(sql);
                        while (rs.next()) {
                                System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3));
                        }
                        rs.close();
                        stmt.close();
                } catch (SQLException e) {
                        e.printStackTrace();
                } finally {
                        DBToolkit.closeConnection(conn);
                }
        } 

        /**
         * 可滚动结果集滚动测试
         */
        public static void testScrollResultSet() {
                Connection conn = DBToolkit.getConnection();
                String sql = "SELECT * FROM book";
                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));
                        } 

                        System.out.println("------前滚操作-----");
                        //将光标移动到此 ResultSet 对象的上一行
                        rs.previous();
                        rs.previous();
                        System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3)); 

                        System.out.println("------绝对定位-----");
                        //将光标移动到此 ResultSet 对象的给定行编号。
                        rs.absolute(3);
                        System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3)); 

                        System.out.println("------移动到第一行-----");
                        //将光标移动到此 ResultSet 对象的第一行。
                        if (rs.first()) {
                                System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3));
                        } 

                        System.out.println("------移动到最后一行-----");
                        //将光标移动到此 ResultSet 对象的第一行。
                        if (rs.last()) {
                                System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3));
                        } 

                        System.out.println("------移动到第一行之前-----");
                        //将光标移动到此 ResultSet 对象的开头,正好位于第一行之前
                        rs.beforeFirst();
                        rs.next();
                        System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3)); 

                        System.out.println("------移动到最后一行之后-----");
                        //将光标移动到此 ResultSet 对象的末尾,正好位于最后一行之后。
                        rs.afterLast();
                        rs.previous();
                        System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3)); 

                        System.out.println("------相对当前行做移动-----");
                        rs.relative(-2);
                        System.out.println("[行号:" + rs.getRow() + "]\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3)); 

                        rs.close();
                        stmt.close();
                } catch (SQLException e) {
                        e.printStackTrace();
                } finally {
                        DBToolkit.closeConnection(conn);
                }
        }
}
 

控制台输出:

[行号:1] 1 aaa a
[行号:2] 2 bbb b
[行号:3] 3 ccc c
[行号:4] 4 ddd d
[行号:5] 5 eee e
[行号:6] 6 fff f
[行号:7] 7 ggg g
[行号:8] 8 hhh h
------前滚操作-----
[行号:7] 7 ggg g
------绝对定位-----
[行号:3] 3 ccc c
------移动到第一行-----
[行号:1] 1 aaa a
------移动到最后一行-----
[行号:8] 8 hhh h
------移动到第一行之前-----
[行号:1] 1 aaa a
------移动到最后一行之后-----
[行号:8] 8 hhh h
------相对当前行做移动-----
[行号:6] 6 fff f
---------原结果集--------
[行号:1] 1 aaa a
[行号:2] 2 bbb b
[行号:3] 3 ccc c
[行号:4] 4 ddd d
[行号:5] 5 eee e
[行号:6] 6 fff f
[行号:7] 7 ggg g
[行号:8] 8 hhh h
---------插入一条记录--------
-------------更新一条记录-------------
---------插入更新后的结果集--------
[行号:1] 1 aaa a
[行号:2] 2 bbb b
[行号:3] 3 uuuu u
[行号:4] 4 ddd d
[行号:5] 5 eee e
[行号:6] 6 fff f
[行号:7] 7 ggg g
[行号:8] 8 hhh h
[行号:9] 9 xxxx x

Process finished with exit code 0

可保存性:设置提交时候是否关闭结果集。

ResultSet.HOLD_CURSORS_OVER_COMMIT :在提交后结果集还可用

ResultSet.CLOSE_CURSORS_AT_COMMIT:在提交时候关闭结果集

由于这些特性比较高级,不同数据库驱动对此实现也不一样。因此在使用JDBC高级特性的时候最好做个测试,以保证程序的可靠性。

当type设置为:ResultSet.TYPE_SCROLL_INSENSITIVE 或者 ResultSet.TYPE_SCROLL_INSENSITIVE 时,游标可以移动,但是移动的位置是[1,count],记住并不是从0开始,否则会报错。

既然可以移动,那么把移动的几个方法解释一下:

rs = statement.executeQuery();  游标指向第一行前面的位置,这个位置是不能获取数据,否则报错:结果集没有当前行

rs.next();  // 游标下移一个位置,如果所在位置有结果集那么返回true,否则返回false

rs.previous(); // 游标上移一个位置,如果所在位置有结果集那么返回true,否则返回false

rs.first(); //  游标指向第一行的位置

rs.last(); //  游标指向最后一行的位置

rs.beforeFirst(); // 游标指向第一行前面的位置 , 这个位置不能获取数据

rs.afterLast(); //  游标指向最后一行后面的位置,这个位置不能获取数据

rs.absolute(index); // 游标移动至index位置,index是[1,count]的任意数字,但是不能超出,否则报错

rs.relative(index); // 游标从当前位置算移动index个位置,也就是相对移动,index可以是负数,但是计算结果同样在[1,count]内

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

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

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

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

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

时间: 2024-11-13 09:27:24

java数据库编程——读写LOB、可滚动和可更新的结果集的相关文章

JAVA数据库编程(JDBC技术)-入门笔记

本菜鸟才介入Java,我现在不急着去看那些基本的语法或者一些Java里面的版本的特征或者是一些晋级的知识,因为有一点.Net的OOP编程思想,所以对于Java的这些语法以及什么的在用到的时候在去发现学习一下.我现在很迫不及待用JAVA想来实现以下对数据库的增删改查.想实现就来看Java是怎么操作数据库的,回想下.Net里你可能会配置web.Config,或者你去写一些DBhelper类然后调用里面的自己定义的一些增删改查的方法,更或者你去配一些数据控件等等往往发现操作基本都是一体化的简单.现在面

Java数据库编程、Java与XML解析技术

Java数据库编程: 1. JDBC概述:JDBC(数据库连接)是Java中提供的一套数据库编程API,它定义了一套用来访问数据库的标准Java类库(位于java.sql和javax.sql包中).用JDBC开发的数据库  应用既可以跨操作系统平台,又可以跨数据库系统平台.    在JDBC的基本操作中,最常用的类和接口包括DriverManager,  Connection,  Statement,  PreparedStatement,  CallableStatement 和 Result

JDBC与JAVA数据库编程

一.JDBC的概念 1. JDBC (Java DataBase Connectivity) Java数据库连接 a) 主要提供java数据库应用程序的API支持 2. JDBC的主要功能 a) 创建和管理与数据源的连接 b) 发送SQL数据命令到数据源 c) 提取并处理由数据源返回的结果集 3. JDBC可分为两层 a) 驱动程序管理接口 b) JDBC API 4. Java.sql包中定义的常用基本的JDBC API a) 类DriverManager:管理一组JDBC驱动程序的基本服务

Java数据库编程及Java XML解析技术

1.JDBC概述 A.  什么是JDBC? Java DataBase Connectivity:是一种用于执行SQL语句的Java API,它由一组用Java语言编写的类和接口组成.通过这些类和接口,JDBC把SQL语句发送给不同类型的数据库进行处理并接收处理结果 B.  JDBC的常用类和接口:DriverManager类, Connection接口, Statement接口, PreparedStatement接口, ResultSet接口 2.JDBC编程步骤 1). 加载驱动程序 Cl

java 数据库编程 学习笔记 不断更新

最近开始学习java,感觉java的数据库编程需要发个随笔记录一下,话不多说 切入正题. 一.数据库访问技术的简介 应用程序  →  执行SQL语句 →数据库 → 检索数据结果 → 应用程序   ( ODBC         JDBC(两个常用的API)) java主要使用的 JDBC驱动程序进行数据库的编程 Java 应用程序 <------> JDBC   <------>  数据库 二.JDBC 的体系结构 应用层 ↓ 驱动层 ↓ 各个接口 •Driver •Connecti

JAVA数据库编程、JAVA XML解析技术

JDBC概述 JDBC是JAVA中提供的数据库编程API curd :数据库增删改 链接字符串:String url = "mysql :/localhost :3306/jdbc/"; connection链接 DriverManager:驱动管理器 execute:发送 close()释放资源 executeUpdte :增删改操作 next()活的结果下一条 Resultset接口:查询结果集 XML概述 Xpath路径表达式 document:指代整个XML文档 ATTLIST

Java 数据库编程 ResultSet 的 使用方法

结果集(ResultSet)是数据中查询结果返回的一种对象,可以说结果集是一个存储查询结果的对象,但是结果集并不仅仅具有存储的功能,他同时还具有操纵数据的功能,可能完成对数据的更新等. 结果集读取数据的方法主要是getXXX() ,他的参数可以使整型表示第几列(是从1开始的),还可以是列名.返回的是对应的XXX类型的值. 如果对应那列时空值,XXX是对象的话返回XXX型的空值,如果XXX是数字类型,如Float等则返回0,boolean返回false. 使用getString()可以返回所有的列

《JAVA数据库编程》

首先,我们需要了解JDBC的概念. JDBC(Java Database Connectivity)是Java中提供的一套数据库编程API,它定义了一套用来访问数据库的标准Java类库(位于java.sql和javax.sql包中).利用JDBC,我们可以用Java编写程序,实现与特定的数据库连接,向数据库发送SQL语句,实现对数据库的特定操作,并对数据库返回的结果进行处理. JDBC编程一般包括如下六个步骤: 1.根据应用程序所用的数据库,选择JDBC驱动程序类型. 2.连接到数据库,得到Co

Java数据库编程中的常用技巧

1.java数据库操作基本流程 2.几个常用的重要技巧: 可滚动.更新的记录集 批量更新 事务处理 java数据库操作基本流程:取得数据库连接 - 执行sql语句 - 处理执行结果 - 释放数据库连接 1.取得数据库连接 1)用DriverManager取数据库连接 例子: String className,url,uid,pwd; className = "oracle.jdbc.driver.OracleDriver"; url = "jdbc:oracle:thin:@