JavaEE学习(三)JBDC

本文是学习JavaEE开发的记录笔记

大纲

JDBC安装

  1. 进入官方网站选择平台独立版下载
  2. 下载后解压缩可以看到.jar包mysql-connector-java-5.1.46-bin.jar,将其放在JDK目录下的lib目录下
  3. 配置classpath

    至此就完成了mysql数据库的JDBC包的安装,在所有java文件中都可以通过import java.sql.*导入mysql的JDBC包了

JDBC简单演示

JDBC进行数据库操作主要有六步:

  • 1.导入包:import java.sql.*;
  • 2.注册JDBC驱动程序:Class.forName(DriverName);
  • 3.创建数据库连接:Connection conn=DriverManager.getConnection(DB_URL,USER,PASS);
  • 4.执行数据库语句操作 :Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(sql);
  • 5.从结果集提取数据:rs.getType(valueName);
  • 6.关闭连接:ResultSet/Statement/Connection.close();
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    //1.导入包
    import java.sql.*;


    public class sqlTest {
    //一些静态数据
    //JDBC驱动类型 以下为mysql驱动
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";

    //JDBC驱动类型对应的数据库URL 以下为mysqlURL格式jdbc:mysql://hostname/databaseName
    static final String DB_URL = "jdbc:mysql://localhost/mt?useUnicode=true&characterEncoding=utf-8&useSSL=false";

    //数据库账号密码
    static final String USER = "root";
    static final String PASS = "";

    public static void main(String[] args) {
    //数据库连接实例
    Connection conn = null;
    //执行语句实例
    Statement stmt = null;
    try{
    //2.注册JDBC驱动程序
    Class.forName("com.mysql.jdbc.Driver");

    //3.创建一个数据库物理连接Connection
    conn = DriverManager.getConnection(DB_URL,USER,PASS);

    //4.执行数据库语句操作Statement
    stmt = conn.createStatement();
    //读操作使用stmt.executeQuery()执行
    String sql;
    sql = "SELECT id,sid,name,description FROM mt_product";
    ResultSet rs = stmt.executeQuery(sql);
    //写操作使用stmt.executeUpdate()执行 如UPDATE/INSERT/DELETE

    //5.从结果集提取数据
    while(rs.next()){
    int id = rs.getInt("id");
    int sid = rs.getInt("sid");
    String name = rs.getString("name");
    String description = rs.getString("description");
    }

    //6.依次关闭数据库连接
    rs.close();
    stmt.close();
    conn.close();

    }catch(SQLException se){
    //处理JDBC操作数据库出错
    se.printStackTrace();
    }catch(Exception e){
    //处理Class.forName即JDBC驱动程序出错
    e.printStackTrace();
    }finally{
    //使用finally关闭数据库连接
    try{
    if(stmt!=null) stmt.close();
    }catch(SQLException se2){
    //不做任何事情
    }
    try{
    if(conn!=null) conn.close();
    }catch(SQLException se){
    se.printStackTrace();
    }
    }
    }
    }

JDBC架构与组件

JDBC体系架构由两层组成:

  • JDBC API:连接应用程序(Java Application)到JDBC驱动管理器(JDBC Driver Manager)
  • JDBC 驱动程序API:连接JDBC驱动管理器(JDBC Driver Manager)到驱动程序(JDBC Driver)

JDBC驱动管理器:确保程序使用正确驱动访问数据源,支持连接到多个异构数据库的多个并发驱动程序

JDBC API提供的接口和类:

  • DriverManager:管理数据库驱动程序列表,使用其DriverManager.getConnection();方法建立数据库连接
  • Driver:处理与数据库服务器的通信,我们很少直接与Driver交互,而是通过DriverManager管理Driver
  • Connection:与数据库所有通信方法的联系来源,如Connection.createStatement()创建语句对象
  • Statement:语句对象,用于将SQL语句提交到数据库,如Statement.executeQuery(读语句)/Statement.executeUpdate(写语句)
  • ResultSet:数据库返回的查询结果集
  • SQLException:数据库应用程序中发生的任何错误

JDBC驱动类型

JDBC驱动程序:JDK附带的java.sql中包含各种类的定义,JDBC驱动程序则实现其中的java.sql.Driver接口使得Java应用可以与数据库服务器进行交互

JDBC驱动程序类型:Sun公司根据其架构可分为四类

  • JDBC-ODBC桥驱动程序
  • JDBC本地API
  • JDBC-Net纯Java
  • 100%纯Java

100%纯Java驱动类型:MySQL Connector/J使用,基于纯Java的驱动程序通过套接字连接与供应商的数据库直接通信,是数据库最高性能的驱动程序,不需要在客户端或服务器安装特殊软件

注册JDBC驱动程序

注册驱动程序是使JVM将Oracle驱动程序的类文件加载到内存中的过程,因此可以将其用作JDBC接口的实现,只需在程序中注册一次就可以

注册驱动程序方法:

  1. Class.forName():将驱动程序的类文件动态加载到内存中,并将其自动注册
    1
    2
    3
    4
    5
    6
    7
    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():
    1
    2
    3
    4
    5
    6
    7
    8
    try {
    Driver myDriver = new com.mysql.jdbc.Driver();
    DriverManager.registerDriver( myDriver );
    }
    catch(ClassNotFoundException ex) {
    System.out.println("Error: unable to load driver class!");
    System.exit(1);
    }

Connection对象:数据库URL配置

注册驱动程序后,使用DriverManager.getConnection()根据对应驱动程序的数据库URL建立连接获取Connectiond对象
JDBC驱动程序与对应数据库URL:

常用的getConnection()构造方法:使用数据库URL+数据库账号+数据库密码

1
2
3
4
String URL = "jdbc:mysql://hostname/databaseName";
String USER = "username";
String PASS = "password"
Connection conn = DriverManager.getConnection(URL, USER, PASS);

数据库交互

数据库连接后进行数据库交互的对象

Statement对象:通过Statement stmt=Connection.createStatement()获得,对象方法有

PreparedStatement对象:通过在SQL语句中使用占位符,使用SetXXX()方法绑定参数

1
2
3
4
5
6
7
8
9
Connection conn = DriverManager.getConnection(DB_URL,USER,PASS);
//SQL语句中使用占位符
String sql = "UPDATE Employees set age=? WHERE id=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
//设置占位符值
stmt.setInt(1, 35);
stmt.setInt(2, 102);
//执行语句
int rows = stmt.executeUpdate();

CallableStatement对象:比PreparedStatement对象更强大的是不仅提供了SetXXX()方法绑定输入参数,还提供getXXX()绑定SQL语句返回的参数值

ResultSet类:结果集

ResultSet对象实现了java.sql.ResultSet接口,可以在创建数据库交互对象时(createStatement(int RSType, int RSConcurrency);)指定ResultSet对象类型和ResultSet的并发性

浏览结果集:结果集对象实质是一个行列表,因此可以通过移动光标遍历结果集,移动光标方法如下

  • beforeFirst()光标移动到第一行之前
  • afterLast()光标移动到最后一行之后
  • boolean first()光标移动到第一行
  • last()光标移动到最后一行
  • boolean absolute(int row)光标移动到row行
  • boolean relative(int row)光标在当前位置向前(row<0)向后(row>0)移row行
  • boolean previous()光标移动到上一行 第一行时返回false
  • boolean next()光标移动到下一行 最后一行时返回false
  • int getRow()返回当前行数
  • moveToInsertRow()光标移动到插入行
  • moveToCurrentRow()光标移回原先行数

查看结果集:
通过列名称/列索引getType(String columnName)/getType(int columnIndex)获取当前行数据

更新结果集:
通过列名称/列索引updateType(String columnName, Type newValue)/updateType(int columnIndex,Type newValue)更新当前行数据

通过更新结果集数据更新数据库:

JDBC数据类型

JDBC驱动程序将Java数据类型与SQL数据类型提供一一对应的映射

NULL值处理:在查询结果集时若数据出现NULL值,需要使用ResultSet对象的wasNull()方法来将SQL的NULL值处理成java的数据类型,值得注意的是,ResultSet.wasNull()方法需要在getXXX()方法后使用

JDBC事务

  1. 启动手动事务支持:Connection.setAutoCommit(false);
  2. 提交事务:Connection.commit();
  3. 回滚事务:Connection.rollback();
  4. 回滚点:Savepoint savepoint=Connection.setSavepoint(“Savepoint1”);rollback(savepoint)仅保存回滚点前的更改
  5. 完整事务框架:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    try{
    conn = DriverManager.getConnection(DB_URL,USER,PASS);
    //启动手动事务支持
    conn.setAutoCommit(false);

    //数据库交互代码

    //提交事务
    conn.commit();
    }catch(SQLException se){
    //若出现错误 回滚事务
    conn.rollback();
    }

JDBC异常

对于JDBC,最常处理的的异常是java.sql.SQLException驱动程序/数据库交互都会发生SQLException异常,我们可以使用try-catch-finally捕获SQLException异常对象进行处理,一般采用SQLException.printStackTrace();打印错误信息,以下有SQLException对象用于检索异常信息的方法

JDBC批量处理

  1. 确认数据库是否支持批量处理:DatabaseMetaData dbmd=Connection.getMetaData();dbmd.supportsBatchUpdates();返回boolean确定数据库是否支持批量更新操作
  2. 取消自动提交:Connection.setAutoCommit(false);
  3. 添加多条SQL语句到Statement对象中:Statement.addBatch(SQL);
  4. 执行SQL语句:int[] count = Statement.executeBatch();会返回整数数组表示相应更新语句的更新计数
  5. 提交事务更改:Connection.commit();
  6. 清除所有添加的批量语句:Statement.clearBatch();

SQL转义

通过转义序列,使得JDBC驱动可以以目标数据库的格式存储相应数据

  1. 日期:{d ‘yyyy-mm-dd’}
  2. 时间:{t ‘hh:mm:ss’}
  3. 日期+时间:{ts ‘yyyy-mm-dd hh:mm:ss’}
  4. DBMS中的标量函数:如SQL函数length获取字符串长度{fn length(‘Hello World’)}
  5. 外部连接:{oj outer-join}

JDBC流数据

JDBC中PreparedStatement对象可以使用输入流和输出流处理数据,例如针对CLOB/BLOB数据等大值数据可以通过转换成ASCII/UNICODE/二进制等流形势存储和读取数据

  • setAsciiStream(int 参数占位符,FileInputStream 文件流,int 文件长度):将文件流转换成ASCII值
  • setCharacterStream(int 参数占位符,FileInputStream 文件流,int 文件长度):将文件流转换成Character值
  • setBinaryStream(int 参数占位符,FileInputStream 文件流,int 文件长度):将文件流转换成Binary值
  • 相对应的ResultSet.getXXXStream(int columnIndex)将对应值转换成输入流InputStream