博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 核心技术Ⅱ--章五:JDBC数据库编程
阅读量:4223 次
发布时间:2019-05-26

本文共 5966 字,大约阅读时间需要 19 分钟。

java数据库编程JDBC

简单的jdbc编程示例:

public class DBTest {    public static void runTest(){        Connection conn = null;        Statement stat = null;        try{            conn = getConn();            stat = conn.createStatement();            ResultSet rs = stat.executeQuery("select 1 from dual");            if(rs.next()){                System.out.println("数据库连接成功!");            }        }catch(Exception e){            e.printStackTrace();        }finally{            //关闭连接            try {                if(stat!= null && !stat.isClosed()){                    stat.close();                }if(conn!= null && !conn.isClosed()){                    conn.close();                }            } catch (SQLException e) {                e.printStackTrace();            }        }    }    public static Connection getConn() throws IOException,SQLException, ClassNotFoundException {        Properties pro = new Properties();        //获取db连接文件输入流        InputStream in = Files.newInputStream(Paths.get("properties", "db.properties"));        pro.load(in);        String driverName = pro.getProperty("driverName");        //手动加载数据库驱动类        Class.forName(driverName);        String url = pro.getProperty("url");        String username = pro.getProperty("username");        String password = pro.getProperty("password");        //获得数据库连接        return DriverManager.getConnection(url, username, password);    }    public static void main(String[] args) throws IOException, SQLException {        runTest();    }}

1、读写LOB

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

从数据库中获取一张图片:

ResultSet rs = stat.executeQuery();if(rs.next()){Blob coverBlob = rs.getBlob(1);Image coverImage = ImageIO.read(coverBlob.getBinaryStream());    }

存储一张图片:

//创建Blob对象Blob coverBlob = connection.createBlob();int offset = 0;//获取输出流OutputStream out = coverBlob.setBinaryStream(offset);将Image写入到输出流中ImageIO.write( (RenderedImage) coverImage, "PNG", out);stat = connection.prepareStatement("INSERT INTO Cover VALUES(?)");tat.setBlob(1, coverBlob);

2、SQL转义

“转义”语法是各种数据库普遍支持的特性,但是数据库使用的是与数据库相关的语法变体,因此,将转义语法转译为特定数据库的语法是JDBC驱动程序的任务之一。

转译日期:{d 'yyyy-mm-dd'}{t 'hh:mm:ss'}{ts 'yyyy-mm-dd hh:mm:ss'}

String sql="INSERT INTO STUDENTS VALUES" +       "(1,'tjy', {d '2001-12-16'})";

按照数据库的不同,将日期转换为数据库的日期格式。

3、获取数据库自动生成的键值

大多数数据库都支持某种在数据库中对行自动编号的机制。这些编号通常作用于主键,尽管JDBC没有提供生成主键的机制,但是,当一条数据插入以后,它可以获取该条数据自动生成的主键。

stat.executeUpdate(insertStatement,Statement.RETURN_GENERATED_KEYS);ResultSet rs = stat.getGeneratedKeys();

4、可滚动和可更新的结果集

前面已经介绍,使用ResultSet接口中的next方法可以迭代遍历结果集中的所有行,对于一个只需要分析数据的程序来说,这已经够了,但是,如果用于展示一张表或查询结果的可视化数据显示,我们通常会希望用户可以在结果集上前后移动。对于可滚动结果集而言,我们可以在其中向前或向后移动,甚至可以跳到任意位置。

默认情况下,结果集是不可滚动和不可更新的。为了从查询中获取可滚动的结果集,必须使用下面的方法得到一个不同的Statement对象:

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

如果要获得预备语句,请调用下面的方法:

PrepareStatement stat = conn.prepareStatement(command,type,concurrency);

下表展示了type、concurrency的所有可能取值

ResultSet类的type值:

解释
TYPE_FORWARD_ONLY 结果集不能滚动(默认值)
TYPE_SCROLL_INSENSITIVE 结果集可以滚动,但对数据库变化不敏感
TYPE_SCROLL_SENSITIVE 结果集可以滚动,且对数据库变化敏感

ResultSet类Concurrency值:

解释
CONCUR_READ_ONLY 结果集不能用于更新数据库(默认)
CONCUR_UPDATABLE 结果集可以用于更新数据库

例如:如果只想滚动遍历结果集,而不想编辑它的数据,那么可以使用以下语句

Statement stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);//通过调用以下方法获得的所有结果集都将是可滚动的ResultSet rs = stat.executeQuery(sql);

注意:即使这样获得的Statement对象得到的ResultSet对象也有可能并不支持滚动,例如一个复杂的查询,可以通过使用ResultSet接口中的getType和getConcurrency方法来查看结果集实际支持的模式。

可滚动的结果集有一个游标,用以指示当前位置。

向前滚动:rs.previous();

向前或向后移动多行(正数:前,负数:后移):rs.relative(n);

获得当前行号:rs.getRow();

first、last、beforeFirst、afterLast这些简便方法用于将游标移动到第一行、最后一行、第一行之前、最后一行之后。

isFirst、isLast、isBeforeFirst、isAfterLast用于判断游标是否在特殊位置上。

可更新的结果集

假设想提高某些图书的价格,但是在执行update语句时,没有一个统一的提价标准,此时,可以根据任意设定的条件,迭代遍历所有的图书并更新他们的价格。

String query = "select * from Books";ResultSet rs = stat.excuteQuery(query);while(rs.next()){  if(...){    double increase = ...    double price = rs.getDouble("price");    //更新结果集中当前行的数据,为同步到数据库中,一旦换行,更新数据无效    rs.updateDouble("Price",price+increase);    //同步当前行数据到数据库中    rs.updateRow();  }}

新插入一行:

//新建一个空白行rs.moveToInsertRow();//插入数据rs.updateString("Title",title);rs.updateDouble("Price",price);//将当前行同步到数据库中rs.insertRow();//移动到插入行之前的行rs.moveToCurrentRow();

5、行集

可滚动的结果集虽然功能强大,却有一个重要的缺陷:在与用户的整个交互过程中,必须始终与数据库保持连接。在这种情况下,我们可以使用行集。RowSet接口扩展自ResultSet接口,无需始终保持与数据库的连接。

5.1、构建行集

以下为javax.sql.rowset包提供的接口,它们都扩展了RowSet接口:

  • cachedRowSet允许在断开连接的状态下执行相关操作。
  • WebRowSet对象代表了一个被缓存的行集。该行集可以保存为XML文件。该文件可以移动到Web应用的其他层中,只要在该层中使用另一个WebRowSet对象重新打开该文件即可。
  • FilteredRowSet和JoinRowSet接口支持对行集的轻量级操作,它们等同于sql中的SELECT和HOIN操作。这两个接口的操作对象时存储在行集中的数据,因此运行时无需连接数据库。
ResultSet result = ...;RowSetFactory factory = RowSetProvider.newFactory();CachedRowSet crs = factory.createCachedRowSet();crs.populate(result);conn.close();

或者也可以让CachedRowSet对象自动建立一个数据库连接。首先,设置数据库参数:

//设置数据库相关参数crs.setURL(url);crs.setUsername(username);crs.setPassword(pwd);//设置查询语句和所有参数crs.setCommand("SELECT * FROM Books WHERE publisher_ID = ?");crs.setString(1,publisherId);//将查询结果填充到行集中//这个方法将建立数据库连接,执行查询操作,填充行集,断开数据库连接crs.execute();

如果查询结果非常大,不想把所有结果都放入行集中,用户可能只是想浏览其中几行而言,在这种情况下,可以指定每一页的尺寸。

CachedRowSet crs = ...;crs.setCommand(command);//每一页20条数据crs.setPageSize(20);crs.execute();//获得下一页数据crs.nextPage();

如果修改了行集中的数据,可以调用下列方法同步到数据库中。

crs.acceptChanges(conn);//或者 行集中保存了连接数据库的参数crs.acceptChanges();

注意:在同步数据库时,同步时首先检查行集中的原始值是否与数据库中的当前值一致,一致,将修改后的值覆盖数据库的当前值,否则,将抛出异常。

6、事务

我们可以将一组语句构成一个事务,当所有语句执行之后,事务可以被提交。否则,如果其中某个语句遇到错误,那么事务将被回滚,就像任何语句都没被执行过一样。

默认情况下,数据库连接处于自动提交模式:每个sql语句一旦被执行,就会立即提交给数据库,一旦提交,将无法回滚。关闭自动提交:

conn.setAutoCommit(false);

多次调用executeUpdate方法:

stat.executeUpdate(command1);stat.executeUpdate(command2);stat.executeUpdate(command3);//没有问题conn.commit();//有问题,可以用try ...catch捕获conn.rollback();

保存点:

Statement stat = conn.createStatement();stat.executeUpdate(command1);Savepoint svpt = conn.setSavepoint();stat.executeUpdate(command2);//没有问题conn.commit();//有问题,可以回滚到保存点 保存点之后的语句就像没有执行过一样conn.rollback(svpt);//需要释放保存点conn.releaseSavepoint(svpt);

转载地址:http://dfwqi.baihongyu.com/

你可能感兴趣的文章
独家 | 一文读懂PySpark数据框(附实例)
查看>>
清华“法律数据科研平台”向校内师生开放试运行
查看>>
终结谷歌AutoML的真正杀手!Saleforce开源TransmogrifAI
查看>>
六个维度、数万条数据帮你揭穿房租大涨的背后(附代码)
查看>>
干货 | 只有100个标记数据,如何精确分类400万用户评论?
查看>>
独家 | 全解用Python建立能源市场算法交易的机器学习框架(附链接)
查看>>
重磅 | 2018年清华大学研究生新生大数据
查看>>
独家 | 初学者的问题:在神经网络中应使用多少隐藏层/神经元?(附实例)
查看>>
资源 | 机器学习必知的15大框架,欢迎补充!
查看>>
基于问题导向与成果产出的教学模式:《大数据与城市规划》特色课程
查看>>
Python 爬取北京二手房数据,分析北漂族买得起房吗?(附完整源码)
查看>>
清华大学AMiner团队发布《超级计算机研究报告》(附下载)
查看>>
第一届全国计算社会科学高端论坛在清华大学举行
查看>>
“还完花呗,再也不用吃土!”是真的吗?(附代码)
查看>>
玩转数据、拥抱智能 | 清华大学大数据能力提升项目宣讲会火热来袭
查看>>
收藏 | 应对程序员面试,你必须知道的8大数据结构
查看>>
避坑指南:数据科学家新手常犯的13个错误(附工具、学习资源链接)
查看>>
智慧城市新探索:摩拜&京东联合利用智能单车数据检测违章停车
查看>>
福利 | 大数据新媒体平台面向清华校内师生开放!
查看>>
独家 | 盘点9个适用所有学科的R数据可视化包(附链接)
查看>>