Java学习(12)——JDBC

简介

JDBC 是连接数据库和 Java 程序的桥梁,通过 JDBC API 可以方便地实现对各种主流数据库的操作。本节将重点讲解 JDBC 的内容。

知识点

  • SQL 简介
  • JDBC
  • 创建数据库
  • 数据库操作
  • JDBC 结果集
  • 插入数据

数据库简介

数据库,简而言之可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据运行新增、截取、更新、删除等操作。

所谓“数据库”系以一定方式储存在一起、能予多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合。一个数据库由多个表空间(Tablespace)构成。

关系数据库

常见的关系型数据库有以下几种:

  • MySQL (MariaDB 、Percona Server)
  • PostgreSQL
  • Microsoft Access
  • Microsoft SQL Server
  • Google Fusion Tables
  • FileMaker
  • Oracle 数据库
  • Sybase
  • dBASE
  • Clipper
  • FoxPro
  • foshub

非关系型数据库(NoSql)

常见非关系数据库:

  • Redis
  • BigTable
  • Cassandra
  • MongoDB
  • CouchDB

SQL 简介

结构化查询语言 (Structured Query Language) 简称 SQL(发音:/ˈes kjuː ˈel/ “S-Q-L”),是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。

结构化查询语言是高级的非过程化编程语言,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同数据库系统,可以使用相同的结构化查询语言作为数据输入与管理的接口。结构化查询语言语句可以嵌套,这使它具有极大的灵活性和强大的功能。

SQL 语法

对于数据库的操作我们肯定是需要结构化查询语句 SQL。

这里我们就回顾一下 SQL 语句,但不会做过多的详细介绍。

创建数据库
CREATE DATABASE 语句用于创建一个新的数据库。语法是:

SQL> CREATE DATABASE DATABASE_NAME;

例子,创建一个名为 EXAMPLE 数据库:

SQL> CREATE DATABASE EXAMPLE;

删除数据库
使用 DROP DATABASE 语句用于删除现有的数据库。语法是:

SQL> DROP DATABASE DATABASE_NAME;

注意:要创建或删除,应该有数据库服务器上管理员权限。请注意,删除数据库将损失所有存储在数据库中的数据。

例子,删除我们刚刚建好的数据库:

SQL> DROP DATABASE EXAMPLE;

创建表
CREATE TABLE 语句用于创建一个新表。语法是:

SQL> CREATE TABLE table_name
(
   column_name column_data_type,
   column_name column_data_type,
   column_name column_data_type
   ...
);

例子,下面的 SQL 语句创建一个有四个属性的 Students 表:

SQL> CREATE TABLE Students
(
   id INT NOT NULL,
   age INT NOT NULL,
   name VARCHAR(255),
   major VARCHAR(255),
   PRIMARY KEY ( id )
);

删除表
DROP TABLE 语句用于删除现有的表。语法是:

SQL> DROP TABLE table_name;

例子,下面的 SQL 语句删除一个名为 Students 表:

SQL> DROP TABLE Students;

插入数据
语法 INSERT 如下,其中 column1, column2 ,依此类推的属性值:

SQL> INSERT INTO table_name VALUES (column1, column2, ...);

例子,下面的 INSERT 语句中插入先前创建的 Students 表:

SQL> INSERT INTO Students VALUES (1, 18, 'Mumu', 'Java');

查询数据
SELECT 语句用于从数据库中检索数据。该语法的 SELECT 是:

SQL> SELECT column_name, column_name, ...
     FROM table_name
     WHERE conditions;

WHERE 子句可以使用比较操作符例如 =, !=, <, >, <=, >=, 以及 BETWEEN 和 LIKE 等操作符。

例子,下面的 SQL 语句从 Students 表选择 id 为 1 的学生,并将该学生的姓名和年龄显示出来:

SQL> SELECT name, age
     FROM Students
     WHERE id = 1;

下面的 SQL 语句从 Students 表中查询姓名中有 om 字样的学生,并将学生的姓名和专业显示出来:

SQL> SELECT name, major
     FROM Students
     WHERE name LIKE '%om%';

更新数据
UPDATE 语句用于更新数据。UPDATE 语法为:

SQL> UPDATE table_name
     SET column_name = value, column_name = value, ...
     WHERE conditions;

例子,下面的 SQL 的 UPDATE 语句表示将 ID 为 1 的学生的 age 改为 20:

SQL> UPDATE Students SET age=20 WHERE id=1;

删除数据
DELETE 语句用来删除表中的数据。语法 DELETE 是:

SQL> DELETE FROM table_name WHERE conditions;

例子,下面的 SQL DELETE 语句删除 ID 为 1 的学生的记录:

SQL> DELETE FROM Students WHERE id=1;

JDBC

JDBC 的全称是 Java Database Connectivity,叫做 Java 数据库连接。它包括了一组与数据库交互的 API,还有与数据库进行通信的驱动程序。

我们要写涉及到数据库的程序,是通过 C 语言或者 C++ 语言直接访问数据库的接口,如下图所示。
在这里插入图片描述
对于不同的数据库,我们需要知道不同数据库对外提供的系统 API,这就影响了我们程序的扩展和跨平台的实现。

那么有没有一种方法来对不同的数据库接口进行统一呢?当然有。我们只需要和最上层接口进行交互,剩下的部分就交给其他各层去处理,我们的任务就变的轻松简单许多。

JDBC 为数据库开发人员提供了一个标准的 API,据此可以构建更高级的工具和接口使数据库开发人员能够用纯 Java API 编写数据库应用程序。

JDBC 连接数据库

涉及到建立一个 JDBC 连接的编程主要有四个步骤:

  1. 导入 JDBC 驱动: 只有拥有了驱动程序我们才可以注册驱动程序完成连接的其他步骤。
  2. 注册 JDBC 驱动程序:这一步会导致 JVM加载所需的驱动类实现到内存中,然后才可以实现 JDBC 请求。
  3. 数据库 URL 指定:创建具有正确格式的地址,指向到要连接的数据库。
  4. 创建连接对象:最后,代码调用 DriverManager 对象的 getConnection() 方法来建立实际的数据库连接。

接下来我们便详细讲解这四步。

导入 JDBC 驱动

需要下载对应数据库的 jdbc 驱动,将其导入到项目中,具体的导入方式根据个人的 IDE 确定,本节课程不使用 IDE,直接使用 javac -cp 命令导入包。

注册 JDBC 驱动程序

我们在使用驱动程序之前,必须注册你的驱动程序。注册驱动程序的本质就是将我们将要使用的数据库的驱动类文件动态的加载到内存中,然后才能进行数据库。比如我们使用的 Mysql 数据库。我们可以通过以下两种方式来注册我们的驱动程序。

1、Class.forName():

动态加载一个类最常用的方法是使用 Java 的 Class.forName() 方法,通过使用这个方法来将数据库的驱动类动态加载到内存中,然后我们就可以使用。

使用 Class.forName() 来注册 Mysql 驱动程序:

try {
   Class.forName("com.mysql.jdbc.Driver");
}
catch(ClassNotFoundException ex) {
   System.out.println("Error: unable to load driver class!");
   System.exit(1);
}

2、DriverManager.registerDriver():

Driver driver = new com.mysql.jdbc.Driver();
DriverManager.registerDriver(driver);

指定数据库连接 URL

当加载了驱动程序,便可以使用 DriverManager.getConnection() 方法连接到数据库了。

这里给出 DriverManager.getConnection() 三个重载方法:

getConnection(String url)

getConnection(String url, Properties prop)

getConnection(String url, String user, String password)

数据库的 URL 是指向数据库地址。下表列出了下来流行的 JDBC 驱动程序名和数据库的 URL。

RDBMSJDBC 驱动程序的名称URL
Mysqlcom.mysql.jdbc.Driverjdbc:mysql://hostname/ databaseName
Oracleoracle.jdbc.driver.OracleDriverjdbc:oracle:thin:@hostname:port Number:databaseName
DB2COM.ibm.db2.jdbc.net.DB2Driverjdbc:db2:hostname:port Number/databaseName
Sybasecom.sybase.jdbc.SybDriverjdbc:sybase:Tds:hostname: port Number/databaseName

创建连接对象

下面三种形式 DriverManager.getConnection() 方法来创建一个连接对象,以 Mysql 为例。getConnection() 最常用形式要求传递一个数据库 URL,用户名 username 和密码 password。

1、使用数据库 URL 的用户名和密码

String URL = "jdbc:mysql://localhost/EXAMPLE";
String USER = "username";
String PASS = "password"
Connection conn = DriverManager.getConnection(URL, USER, PASS);

2、只使用一个数据库 URL

然而,在这种情况下,数据库的 URL,包括用户名和密码。

String URL = "jdbc:mysql://localhost/EXAMPLE?user=root&password=0909";
//Mysql URL的参数设置详细可以查阅相关资料
Connection conn = DriverManager.getConnection(URL);

3、使用数据库的 URL 和一个 Properties 对象

import java.util.*;

String URL = "jdbc:mysql://localhost/EXAMPLE";
Properties pro = new Properties( );

//Properties对象,保存一组关键字-值对
pro.put( "user", "root" );
pro.put( "password", "" );

Connection conn = DriverManager.getConnection(URL, pro);

4、关闭 JDBC 连接

conn.close();

创建数据库

在使用数据库之前第一件事情就是创建数据库,这里我们使用 JDBC 来创建数据库。

import java.sql.*;

public class CreateDatabase {
    public static void main(String[] args){
        Connection connection = null;
        try {
            //加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            //打开数据库连接 第一个参数为数据库地址  后面2个参数分别为数据库用户名和密码
            // 实验楼中 MySQL 的用户名为: root, 密码为空。
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/","root","");
            //创建Statement
            Statement statement = connection.createStatement();
            //执行sql
            statement.execute("create database EXAMPLE");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                //关闭连接
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

启动 mysql:

$ sudo service mysql start

编译运行(需要带上 mysql-connector-java-5.1.45.jar):

$ wget http://labfile.oss.aliyuncs.com/courses/1230/mysql-connector-java-5.1.47.jar
$ javac -cp mysql-connector-java-5.1.47.jar CreateDatabase.java
$ java -cp .:mysql-connector-java-5.1.47.jar CreateDatabase

数据库操作

当连接上了数据库后,就需要通过 sql 语句对数据库进行操作。随着 Java 语言应用面的逐步拓宽,Sun 公司开发了一个标准的 SQL 数据库访问接口———JDBC API。它可以使 Java 编程人员通过一个一致的接口,访问多种关系数据库。而今天我们就来学习一下,如何利用 JDBC 的一些核心 API 与数据库进行交互。

通过使用 JDBC Statement, CallableStatement 和 PreparedStatement 接口定义的方法和属性,使可以使用 SQL 或 PL/SQL 命令和从数据库接收数据。它们还定义了许多方法,帮助消除 Java 和数据库之间数据类型的差异。

接口应用场景
Statement当在运行时使用静态 SQL 语句时(Statement 接口不能接收参数)
CallableStatement当要访问数据库中的存储过程时(CallableStatement 对象的接口还可以接收运行时输入参数)
PreparedStatement当计划多次使用 SQL 语句时(PreparedStatement 接口接收在运行时输入参数)

Statement

我们要使用 Statement 接口,第一步肯定是创建一个 Statement 对象了。我们需要使用 Connection 对象的 createStatement() 方法进行创建。

Statement stmt = null;
try {
   stmt = conn.createStatement( );
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   . . .
}

一旦创建了一个 Statement 对象,我们就可以用它来执行 SQL 语句了,首先我们先来看看 Statement 里面有哪些方法吧!

方法说明
boolean execute(String SQL)如果 ResultSet 对象可以被检索返回布尔值 true,否则返回 false。使用这个方法来执行 SQL DDL 语句,或当需要使用真正的动态 SQL
int executeUpdate(String SQL)用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQLDDL(数据定义语言)语句。返回值是一个整数,指示受影响的行数(即更新计数)
ResultSet executeQuery(String SQL)返回 ResultSet 对象。用于产生单个结果集的语句,例如 SELECT 语句

正如关闭一个 Connection 对象来释放数据库连接资源,出于同样的原因,也应该关闭 Statement 对象。

Statement stmt = null;
try {
   stmt = conn.createStatement( );
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   stmt.close();
}

注:如果关闭了 Connection 对象首先它会关闭 Statement 对象,然而应该始终明确关闭 Statement 对象,以确保正确的清除。

PreparedStatement

PreparedStatement 接口扩展了 Statement 接口,有利于高效地执行多次使用的 SQL 语句。我们先来创建一个 PreparedStatement 对象。 Statement 为一条 SQL 语句生成执行计划。如果要执行两条 SQL 语句,会生成两个执行计划。一万个查询就生成一万个执行计划!

select colume from table where colume=1;
select colume from table where colume=2;

PreparedStatement 用于使用绑定变量重用执行计划。

select colume from table where colume=:x;

通过 set 不同数据,只需要生成一次执行计划,并且可以重用。

PreparedStatement pstmt = null;
try {

/*
在JDBC中所有的参数都被代表?符号,这是已知的参数标记。在执行SQL语句之前,必须提供值的每一个参数。
*/
   String SQL = "Update Students SET age = ? WHERE id = ?";
   pstmt = conn.prepareStatement(SQL);
   . . .
}
/*

setXXX()方法将值绑定到参数,其中XXX表示希望绑定到输入参数值的 Java 数据类型。如果忘了提供值,将收到一个 SQLException。
*/
catch (SQLException e) {
   . . .
}
finally {
//同理,我们需要关闭 PreparedStatement 对象
   pstmt.close();
}

说了这么多,我们手动操作一下吧。

1、先创建数据库和相应的内容:

sudo service mysql start
#  MySQL 的用户名为: root, 密码为空。
mysql -u root
create database EXAMPLE;
use EXAMPLE

在这里插入图片描述

create table Students
(
id int not null,
age int not null,
name varchar(255),
primary key(id)
);
insert into Students values(1,18,'Tom'),
(2,20,'Aby'),(4,20,'Tomson');

在这里插入图片描述

import java.sql.*;

public class JdbcTest {
   // JDBC 驱动器的名称和数据库地址
   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
   static final String DB_URL = "jdbc:mysql://localhost/EXAMPLE";


   static final String USER = "root";
   static final String PASS = "";

   public static void main(String[] args) {
       Connection conn = null;
       PreparedStatement stmt = null;
       try{
           //注册 JDBC 驱动器
           Class.forName("com.mysql.jdbc.Driver");

           //打开连接
           System.out.println("Connecting to database...");
           conn = DriverManager.getConnection(DB_URL,USER,PASS);

           //执行查询
           System.out.println("Creating statement...");
           //这里我们要更改一个同学的年龄,参数待定
           String sql = "UPDATE Students set age=? WHERE id=?";
           stmt = conn.prepareStatement(sql);

           //将值绑定到参数,参数从左至右序号为1,2...
           stmt.setInt(1, 22);  // 绑定 age 的值(序号为1)
           stmt.setInt(2, 1); // 绑定 ID 的值

           // 更新 ID 为1的同学的年龄
           int rows = stmt.executeUpdate();
           System.out.println("被影响的行数 : " + rows );

           // 查询所有记录,并显示.
           sql = "SELECT id, name, age FROM Students";
           ResultSet rs = stmt.executeQuery(sql);

           //处理结果集
           while(rs.next()){
               //检索
               int id  = rs.getInt("id");
               int age = rs.getInt("age");
               String name = rs.getString("name");


               //显示
               System.out.print("ID: " + id);
               System.out.print(", Age: " + age);
               System.out.print(", Name: " + name);
               System.out.println();
           }
           //清理
           rs.close();
           stmt.close();
           conn.close();
       }catch(SQLException se){
           se.printStackTrace();
       }catch(Exception e){
           e.printStackTrace();
       }finally{
           try{
               if(stmt!=null)
                   stmt.close();
           }catch(SQLException se2){
           }
    try{
         if(conn!=null)
                 conn.close();
      }catch(SQLException se){
              se.printStackTrace();
          }
       }
           System.out.println("Goodbye!");
   }
}

编译运行:

$ wget http://labfile.oss.aliyuncs.com/courses/1230/mysql-connector-java-5.1.47.jar
$ javac -cp .:mysql-connector-java-5.1.47.jar JdbcTest.java
$ java -cp .:mysql-connector-java-5.1.47.jar JdbcTest

在这里插入图片描述

CallableStatement

CallableStatement 对象为所有的 DBMS 提供了一种以标准形式调用存储过程的方法。存储过程储存在数据库中。对储存过程的调用是 CallableStatement 对象所含的内容。三种类型的参数有:IN,OUT 和 INOUT。PreparedStatement 对象只使用 IN 参数。 CallableStatement 对象可以使用所有三个

参数描述
IN它的值是在创建 SQL 语句时未知的参数,将 IN 参数传给 CallableStatement 对象是通过 setXXX() 方法完成的
OUT其值由它返回的 SQL 语句提供的参数。从 OUT 参数的 getXXX() 方法检索值
INOUT同时提供输入和输出值的参数,绑定的 setXXX() 方法的变量,并使用 getXXX() 方法检索值

在 JDBC 中调用存储过程的语法如下所示。注意,方括号表示其间的内容是可选项;方括号本身并不是语法的组成部份。

{call 存储过程名[(?, ?, ...)]}

返回结果参数的过程的语法为:

{? = call 存储过程名[(?, ?, ...)]}

不带参数的存储过程的语法类似:

{call 存储过程名}

CallableStatement 对象是用 Connection 方法 prepareCall 创建的。

CallableStatement cstmt = null;
try {
   String SQL = "{call getEXAMPLEName (?, ?)}";
   cstmt = conn.prepareCall (SQL);
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   cstmt.close();
}

CallableStatement 接口就不再详细地讲解了,可以自己查阅相关的资料,对 CallableStatement 进行深入学习。

JDBC 结果集

结果集通常是通过执行查询数据库的语句生成,表示数据库查询结果的数据表。

ResultSet 介绍

ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。光标可以方便我们对结果集进行遍历。默认的 ResultSet 对象不可更新,仅有一个向前移动的光标。因此,只能迭代它一次,并且只能按从第一行到最后一行的顺序进行。

ResultSet 接口的方法可分为三类:

  • 导航方法:用于移动光标
  • 获取方法:用于查看当前行的光标所指向的列中的数据
  • 更新方法:用于更新当前行的列中的数据

JDBC 提供下列连接方法来创建所需的 ResultSet 语句:

createStatement(int RSType, int RSConcurrency);

prepareStatement(String SQL, int RSType, int RSConcurrency);

prepareCall(String sql, int RSType, int RSConcurrency);

RSType 表示 ResultSet 对象的类型,RSConcurrency 是 ResultSet 常量,用于指定一个结果集是否为只读或可更新。

ResultSet 的类型,如果不指定 ResultSet 类型,将自动获得一个是 TYPE_FORWARD_ONLY:

类型描述
ResultSet.TYPE_FORWARD_ONLY游标只能向前移动的结果集
ResultSet.TYPE_SCROLL_INSENSITIVE游标可以向前和向后滚动,但不及时更新,就是如果数据库里的数据修改过,并不在 ResultSet 中反应出来
ResultSet.TYPE_SCROLL_SENSITIVE游标可以向前和向后滚动,并及时跟踪数据库的更新,以便更改 ResultSet 中的数据

并发性的 ResultSet,如果不指定任何并发类型,将自动获得一个为 CONCUR_READ_ONLY

并发描述
ResultSet.CONCUR_READ_ONLY创建结果集只读。这是默认的
ResultSet.CONCUR_UPDATABLE创建一个可更新的结果集

如初始化一个 Statement 对象来创建一个双向、可更新的 ResultSet 对象:

try {
   Statement stmt = conn.createStatement(
                           ResultSet.TYPE_SCROLL_INSENSITIVE,
                           ResultSet.CONCUR_UPDATABLE);
}
catch(Exception ex) {
   ....
}
finally {
   ....
}

导航

我们在上面已经知道了,导航方法是用于移动光标的。我们先来看一看,在 ResultSet 接口中有哪些方法会涉及光标的移动。

方法说明
public void beforeFirst() throws SQLException将光标移动到正好位于第一行之前
public void afterLast() throws SQLException将光标移动到刚刚结束的最后一行
public boolean first() throws SQLException将光标移动到第一行
public void last() throws SQLException将光标移动到最后一行
public boolean absolute(int row) throws SQLException将光标移动到指定的行
public boolean relative(int row) throws SQLException从它目前所指向向前或向后移动光标行的给定数量
public boolean previous() throws SQLException将光标移动到上一行。上一行关闭的结果集此方法返回 false
public boolean next() throws SQLException将光标移动到下一行。如果没有更多的行结果集中的此方法返回 false
public int getRow() throws SQLException返回的行号,该光标指向的行
public void moveToInsertRow() throws SQLException将光标移动到一个特殊的行,可以用来插入新行插入到数据库中的结果集。当前光标位置被记住
public void moveToCurrentRow() throws SQLException移动光标返回到当前行,如果光标在当前插入行,否则,这个方法不执行任何操作

什么也不说了,我们还是看代码吧!

import java.sql.*;

public class JdbcTest {
   // JDBC 驱动器名称 和数据库地址
   static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
   //数据库的名称为 EXAMPLE
   static final String DB_URL = "jdbc:mysql://localhost/EXAMPLE";

   // 数据库用户和密码
   static final String USER = "root";
   static final String PASS = "";

   public static void main(String[] args) {
       Connection conn = null;
       Statement stmt = null;
       try{
           //注册JDBC 驱动程序
           Class.forName("com.mysql.jdbc.Driver");

           //打开连接
           System.out.println("Connecting to database...");
           conn = DriverManager.getConnection(DB_URL,USER,PASS);



           System.out.println("Creating statement...");
           //创建所需的ResultSet,双向,只读
           stmt = conn.createStatement(
                           ResultSet.TYPE_SCROLL_INSENSITIVE,
                           ResultSet.CONCUR_READ_ONLY);
           String sql;
           sql = "SELECT id, name, age FROM Students";
           ResultSet rs = stmt.executeQuery(sql);

           // 将光标移到最后一行
           System.out.println("Moving cursor to the last...");
           rs.last();

           //处理结果集
           System.out.println("Displaying record...");
           int id  = rs.getInt("id");
           int age = rs.getInt("age");
           String name = rs.getString("name");


           //显示
           System.out.print("ID: " + id);
           System.out.print(", Age: " + age);
           System.out.print(", Name: " + name);
           System.out.println();

           // 将光标移到第一行
           System.out.println("Moving cursor to the first row...");
           rs.first();


           System.out.println("Displaying record...");
           id  = rs.getInt("id");
           age = rs.getInt("age");
           name = rs.getString("name");


           //显示
           System.out.print("ID: " + id);
           System.out.print(", Age: " + age);
           System.out.print(", Name: " + name);

           //将光标移至下一行
           System.out.println("Moving cursor to the next row...");
           rs.next();


           System.out.println("Displaying record...");
           id  = rs.getInt("id");
           age = rs.getInt("age");
           name = rs.getString("name");

           // 显示
           System.out.print("ID: " + id);
           System.out.print(", Age: " + age);
           System.out.print(", Name: " + name);

           rs.close();
           stmt.close();
           conn.close();
       }catch(SQLException se){
           se.printStackTrace();
       }catch(Exception e){
           e.printStackTrace();
       }finally{
           try{
               if(stmt!=null)
                   stmt.close();
           }catch(SQLException se2){
           }
           try{
               if(conn!=null)
                   conn.close();
           }catch(SQLException se){
               se.printStackTrace();
           }
       }
       System.out.println("Goodbye!");
   }
}

获取

ResultSet 接口中我们经常使用 get 方法来查看结果集。

方法说明
public int getInt(String columnName) throws SQLException当前行中名为 ColumnName 列的值
public int getInt(int columnIndex) throws SQLException当前行中指定列的索引的值。列索引从 1 开始,意味着一个行的第一列是 1,行的第二列是 2,依此类推

当然还有 getString() 等等。

代码示例参看上面的示例

更新

更新的方法如下:

方法说明
public void updateString(int columnIndex, String s) throws SQLException指定列中的字符串更改为 s 的值
public void updateString(String columnName, String s) throws SQLException类似于前面的方法,不同之处在于由它的名称,而不是它的索引指定的列

类似的还有 updateDouble() 等等。

我们在更新了结果集中的内容,当然需要更新一下数据库了。我们可以调用下面的方法更新数据库。

方法说明
public void updateRow()通过更新数据库中相应的行更新当前行
public void deleteRow()从数据库中删除当前行
public void refreshRow()刷新在结果集的数据,以反映最新变化在数据库中
public void cancelRowUpdates()取消所做的当前行的任何更新
public void insertRow()插入一行到数据库中。当光标指向插入行此方法只能被调用

我们这里对上面的方法做一个小小的举例:

Statement stmt = conn.createStatement(
                           ResultSet.TYPE_SCROLL_INSENSITIVE,
                           ResultSet.CONCUR_UPDATABLE);

String sql = "SELECT id, name, age FROM Students";
ResultSet rs = stmt.executeQuery(sql);

//结果集中插入新行
rs.moveToInsertRow();
rs.updateInt("id",5);
rs.updateString("name","John");
rs.updateInt("age",21);
//更新数据库
rs.insertRow();

JDBC 事务

我们在编写 java 程序的时候,在默认情况下,JDBC 连接是在自动提交模式下,即每个 SQL 语句都是在其完成时提交到数据库。但有时候我们为了提高程序运行的性能或者保持业务流程的完整性,以及使用了分布式事务管理方式,这个时候我们可能想关闭自动提交而自己管理和控制自己的事务。

让多条 SQL 在一个事务中执行,并且保证这些语句是在同一时间共同执行的时候,我们就应该为这多条语句定义一个事务。一个事务是把单个 SQL 语句或一组 SQL 语句作为一个逻辑单元,并且如果事务中任何语句失败,则整个事务失败。

如果我们要启动一个事务,而不是让 JDBC 驱动程序默认使用 auto-commit 模式支持。这个时候我们就要使用 Connection 对象的 setAutoCommit() 方法。我们传递一个布尔值 false 到 setAutoCommit() 中,就可以关闭自动提交。反之我们传入一个 true 便将其重新打开。

例如:

Connection conn = null;
conn = DriverManager.getConnection(URL);
//关闭自动提交
conn.setAutoCommit(false);

我们关闭了自动提交后,如果我们要提交数据库更改怎么办呢?这时候就要用到我们的提交和回滚了。我们要提交更改,可以调用 commit() 方法:

conn.commit();

尤其不要忘记,在 catch 块内添加回滚事务,表示操作出现异常,撤销事务:

conn.rollback();

插入数据

JDBC 插入数据使用的频率非常高,接下来说明如何使用 JDBC 插入数据。

编程实战

创建数据库(若之前已经创建了 Students 表需提前删除再操作)

总结

本节主要讲解 Java 如何通过 JDBC 对数据库链接以及操作,主要包含以下知识点:

  • SQL 简介
  • JDBC
  • 创建数据库
  • 数据库操作
  • JDBC 结果集
  • 插入数据
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值