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);

java 核心技术Ⅱ--章五:JDBC数据库编程相关推荐

  1. 为什么使用JDBC数据库编程

    为什么使用JDBC数据库编程 本文节选自<21天学通JAVA>一书 在JDBC数据库编程中经常要使用ODBC.所以,在讲述JDBC的驱动程序分类之前,首先介绍什么是ODBC.ODBC是指O ...

  2. JDBC 数据库编程基础

    JDBC 数据库编程基础 安装MySQL 进入官网下载页面:https://www.mysql.com/cn/downloads/ 以下红色横线标记的为mysql社区版,是免费的mysql版本: 接下 ...

  3. Java之十五 JDBC编程

    视频课堂:https://edu.csdn.net/course/play/8222 有了JDBC,向各种关系数据发送SQL语句就是一件很容易的事.换言之,有了JDBCAPI,就不必为访问Sybase ...

  4. [java] JDBC数据库编程

    JDBC(Java Database Connectivity) Java数据库连接技术 官方JDK中提供的与JDBC有关的API都在java.sql包里面 API(Application Progr ...

  5. Java核心技术第五章——2.Object类

    Object类:所有类的超类 Object类是Java中所有类的始祖,在Java中每个类都是由它扩展而来的.但是并不需要这样写: public class Emloyee extends Object ...

  6. JDBC数据库编程:callableStatement接口

    了解MySQL存储过程建立, 了解存储过程中参数传递的三种方式 了解callablestatement调用存储过程操作. 因为在现在开发中,使用存储过程的地方越来越少,所以,对于存储过程使用,只需要了 ...

  7. mysql jdbc关闭连接_【B站Java两分钟】JDBC数据库简单使用,封装连接,关闭

    使用DBUtil类,封装两个静态方法,一个得到连接方法,一个关闭连接方法,以MySQL为例: import java.sql.*; public class DBUtil { //创建连接 publi ...

  8. 新书推荐 | Java核心技术 卷II 高级特性(原书第11版)

    新书推荐 <Java核心技术 卷II 高级特性(原书第11版)> 长按二维码 了解及购买 全新第11版!针对Java SE9.10.11全面更新!Java领域极具影响力和价值的著作之一,与 ...

  9. 疯狂Java讲义(五)----第一部分

    1.定义类: 对一个类定义而言,可以包含三种最常见的成员:构造器.成员变量和方法,三种成员都可以定义零个或多个,如果三种成员都只定义零个,就是定义了一个空类,这没有太大的实际意义. 类里各成员之间的定 ...

最新文章

  1. Java并发编程之——BlockingQueue(队列)
  2. libcurl远程获取文件大小源码
  3. Linux系统下RAID和LVM的实现
  4. 876. Middle of the Linked List - LeetCode
  5. RHEL5 kickstart 安装小结
  6. Vue 新增的$attrs与$listeners的详解
  7. PHP学习之PHP的语法糖
  8. 十三、前端基本功:DOM练习
  9. 作者:谢华美(1976-),男,中国人民银行征信中心数据部副总经理,主要研究方向为数据挖掘。...
  10. 基于JAVA+SpringBoot+Mybatis+MYSQL的疫情信息分析管理系统
  11. K3/Cloud 用插件打开一张已存在的单据
  12. Delphi 10.4.2 (RAD Studio 10.4.2 )安装教程图解
  13. 全国企业税收调查数据(2007-2016)共10年数据,均未脱敏。可通过纳税人识别号,识别具体企业名称和地区信息等,可匹配中国工业企业数据库,中国出口海关统计数据、中国企业污染排放数据库、中国海关数据
  14. vue 日历插件ele-calendar
  15. z8350cpu linux,跑分 Intel Z8350小有提升_平板电脑评测-中关村在线
  16. AE常用快捷键及最常用功能说明
  17. SSD-caffe踩keng
  18. 南宁二中三中高考2021成绩查询,2021广西重点高中名单及排名
  19. 精心收集的几十个ASP编程网址
  20. linux jmap命令详解,jmap命令 linux jmap如何使用

热门文章

  1. voliate 关键字
  2. docker可用容量 查看_查询docker中磁盘使用量大的容器
  3. KSZ9031芯片升级KSZ9131,内核驱动文件
  4. [英语单词] Kernel:upstream/downstream;上下游
  5. 滴滴橙心优选大收缩:研发员工已裁掉一半,最晚11月关全国业务
  6. SQL查询结果单位换算后保留两位小数
  7. 流浪星球 planet
  8. 文献阅读(168)强化学习 Routerless NoC
  9. 如何在R语言中读取数据
  10. Linux下的Framebuffer编程