java基础11JDBC

JDBC

1.数据库访问技术

DBMS(DataBase Management System)是指数据库管理系统

  • Oracle公司的Oracle系列;

  • Microsoft公司的Access系列和SQL Server系列;

  • Microsoft公司早期的FoxPro;

  • IBM公司的DB2;

  • Sybase公司的Sybase;

  • 还有自由开源的MySQL等等。

ODBC(Open DataBase Connectivity)指开放式数据库连接,是由Microsoft公司提供的应用程序接口

  • 负责连接各种不同产商和类型的DBMS,然后为各种不同的编程语言提供查询、插入、修改和删除数据的功能

  • 在各种不同的DBMS和各种不同的编程语言之间架设了一座通用的桥梁。

  • 就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换

2.JDBC

2.1体系

JDBC(Java DataBase Connectivity)是由Sun Microsystem公司提供的API(Application Programming Interface应用程序编程接口

它为Java应用程序提供了一系列的类,使其能够快速高效地访问数据库,只需使用相关的对象完成对数据库的操作。

 

 

 

2.2 连接数据库

JDBC连接数据库有4种驱动类型:

  • JDBC-ODBC桥驱动

  • 纯Java驱动

  • 本地API部分Java驱动

  • JDBC网络纯Java驱动

2.2.1 要素

(1)Driver

java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。

  • Oracle的驱动:oracle.jdbc.driver.OracleDriver

  • mySql的驱动: com.mysql.jdbc.Driver

使用:加入jar包

  • 加载驱动:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名

    • Class.forName(“com.mysql.jdbc.Driver”);

  • 注册驱动:DriverManager 类是驱动程序管理器类,负责管理驱动程序

    • 使用DriverManager.registerDriver(com.mysql.jdbc.Driver)来注册驱动

    • 通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类包含了静态代码块,在这个静态代码块中,会调用 DriverManager.registerDriver() 方法来注册自身的一个实例。

(2)url

URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。

JDBC URL的标准由三部分组成,各部分间用冒号分隔。

  • jdbc:子协议:子名称

  • 协议:JDBC URL中的协议总是jdbc

  • 子协议:子协议用于标识一个数据库驱动程序

  • 子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息。包含主机名(对应服务端的ip地址),端口号,数据库名

MySQL的连接URL编写方式:

  • jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=值&参数=值

  • jdbc:mysql://localhost:3306/atguigu

  • jdbc:mysql://localhost:3306/atguigu?useUnicode=true&characterEncoding=utf8(如果JDBC程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集)

  • jdbc:mysql://localhost:3306/atguigu?user=root&password=123456

(3)用户名密码:字符串形式

2.2.2 连接数据库

Class.getResourceAsStream()方法动态获取某个文件的资源

Java中的getResourceAsStream有以下几种:

  1. Class.getResourceAsStream(String path) : path 不以’/'开头时默认是从此类所在的包下取资源,以’/'开头则是从ClassPath根下获取。通过path构造一个绝对路径,由ClassLoader获取资源。

  2. Class.getClassLoader.getResourceAsStream(String path) :默认从ClassPath根下获取,path不能以’/'开头,由ClassLoader获取资源。

  3. ServletContext. getResourceAsStream(String path):默认从WebAPP根目录下取资源,Tomcat下path是否以’/'开头无所谓,当然这和具体的容器实现有关。

  4. Jsp下的application内置对象就是上面的ServletContext的一种实现。

public  void testConnection() throws Exception {
  //1.加载配置文件
       InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");//类名.class.getClassLoader()
       Properties pros = new Properties();
       pros.load(is);
       
       //2.读取配置信息或者直接写入字符串
       String user = pros.getProperty("user");
       String password = pros.getProperty("password");
       String url = pros.getProperty("url");
       String driverClass = pros.getProperty("driverClass");

       //3.加载驱动
       Class.forName(driverClass);

       //4.获取连接
       Connection conn = DriverManager.getConnection(url,user,password);
       System.out.println(conn);

  }

配置文件声明在工程的src目录下:【jdbc.properties】

user=root
password=fremont
url=jdbc:mysql://localhost:3306/sqltest
driverClass=com.mysql.jdbc.Driver

使用配置文件的方式保存配置信息,在代码中加载配置文件

  • 实现了代码和数据的分离,如果需要修改配置信息,直接在配置文件中修改,不需要深入代码

  • 如果修改了配置信息,省去重新编译的过程。

 

3.JDBC开发

java.sql包是Java内置的包,包含了一系列用于与数据库进行通信的类和接口

import java.sql.*;

3.1 常用API

接口名称说明
Connection 连接对象,连接数据库
Driver 创建连接对象
Statement 语句对象,用于执行SQL语句,并将数据检索到结果集对象中
PreparedStatement 预编译语句对象,用于执行预编译SQL语句,效率高
CallableStatement 存储过程语句对象,用于调用执行存储过程
ResultSet 结果集对象,包含执行SQL语句后返回的数据的集合
类名说明
SQLException 数据库异常类
DriverManager 驱动程序管理类
Date 日期类
TimeStamp 时间戳,纳秒级

3.2 常用API详解

3.2.1 Driver,DriverManager

装载MySql驱动:Class.forName("com.mysql.jdbc.Driver");

DriverManager:驱动管理对象。这个类管理数据库驱动程序的列表。确定内容是否符合从Java应用程序使用的通信子协议正确的数据库驱动程序的连接请求。

3.2.2 Connection

Connection与特定数据库的连接(会话),在连接上下文中执行sql语句并返回结果。

Connection conn = DriverManager.getConnection(url, user, password);

方法名说明
createStatement() 创建向数据库发送sql的statement对象。
prepareStatement(sql) 创建向数据库发送预编译sql的PrepareSatement对象。
prepareCall(sql) 创建执行存储过程的callableStatement对象。
setAutoCommit(boolean autoCommit) 设置事务是否自动提交。
commit() 在链接上提交事务。
rollback() 在此链接上回滚事务。

3.2.3 Statement

执行静态SQL语句并返回它所生成结果的对象

名称说明
Statement connection.createStatement创建,用于发送简单的SQL语句(不带参数
PreparedStatement 继承自Statement接口,由preparedStatement创建,用于发送含有一个或多个参数的SQL语句。PreparedStatement对象比Statement对象的效率更高,并且可以防止SQL注入,所以我们一般都使用PreparedStatement。
CallableStatement 继承自PreparedStatement接口,由方法prepareCall创建,用于调用存储过程。
方法名说明
execute(String sql) 运行语句,返回是否有结果集
executeQuery(String sql) 运行select语句,返回ResultSet结果集。
executeUpdate(String sql) 运行insert/update/delete操作,返回更新的行数。
addBatch(String sql) 把多条sql语句放到一个批处理中。
executeBatch() 向数据库发送一批sql语句执行。

使用Statement操作数据表存在弊端:

  • 问题一:存在拼串操作,繁琐

  • 问题二:存在SQL注入问题:用户输入数据中注入非法的 SQL 语句段或命令

 

通常使用PreparedStatement:防止 SQL 注入

PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示

调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数.

setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值

 

3.2.4 ResultSet

ResultSet这些对象保存从数据库后,执行使用Statement对象的SQL查询中检索数据。

作为一个迭代器,可以通过移动它来检索下一个数据

方法名说明
getString(int index)、getString(String columnName) 获得在数据库里是varchar、char等类型的数据对象。
getFloat(int index)、getFloat(String columnName) 获得在数据库里是Float类型的数据对象。
getDate(int index)、getDate(String columnName) 获得在数据库里是Date类型的数据。
getBoolean(int index)、getBoolean(String columnName) 获得在数据库里是Boolean类型的数据。
getObject(int index)、getObject(String columnName) 获取在数据库里任意类型的数据。
方法名说明
next() 移动到下一行
Previous() 移动到前一行
absolute(int row) 移动到指定行
beforeFirst() 移动resultSet的最前面。
afterLast() 移动到resultSet的最后面。

调用PreparedStatement 的 executeQuery() 方法,查询结果是一个ResultSet 对象

ResultSet 返回的实际上就是一张数据表。

有一个指针指向数据表的第一条记录的前面。

通过 ResultSet 对象的 next() 方法移动到下一行

调用 next()方法检测下一行是否有效。若有效,该方法返回 true,且指针下移。相当于Iterator对象的 hasNext() 和 next() 方法的结合体。

3.2.5 ResultSetMetaData

用于获取关于 ResultSet 对象中列的类型和属性信息的对象

ResultSetMetaData meta = rs.getMetaData();//调用 ResultSet 的 getMetaData() 方法

getColumnName(int column)获取指定列的名称
getColumnLabel(int column): 获取指定列的别名
getColumnCount(): 返回当前 ResultSet 对象中的列数。
getColumnClassName(int column): 检索指定列的特定的类型名称
getColumnTypeName(int column): 检索指定列的数据库特定的类型名称
getColumnDisplaySize(int column): 指示指定列的最大标准宽度,以字符为单位。
isNullable(int column): 指示指定列中的值是否可以为 null。

 

3.2.6 Java与SQL数据类型转换

//获取java.sql.Date类型的当前系统时间

java.sql.Date currentDate = new java.sql.Date(System.currentTimeMillis());

类型名称显示长度数据库类型JAVA类型JDBC类型索引(int)
VARCHAR L+N VARCHAR java.lang.String 12
CHAR N CHAR java.lang.String 1
BLOB L+N BLOB java.lang.byte[] -4
TEXT 65535 VARCHAR java.lang.String -1
INTEGER 4 INTEGER UNSIGNED java.lang.Long 4
TINYINT 3 TINYINT UNSIGNED java.lang.Integer -6
SMALLINT 5 SMALLINT UNSIGNED java.lang.Integer 5
MEDIUMINT 8 MEDIUMINT UNSIGNED java.lang.Integer 4
BIT 1 BIT java.lang.Boolean -7
BIGINT 20 BIGINT UNSIGNED java.math.BigInteger -5
FLOAT 4+8 FLOAT java.lang.Float 7
DOUBLE 22 DOUBLE java.lang.Double 8
DECIMAL 11 DECIMAL java.math.BigDecimal 3
BOOLEAN 1 同TINYINT    
ID 11 PK (INTEGER UNSIGNED) java.lang.Long 4
DATE 10 DATE java.sql.Date 91
TIME 8 TIME java.sql.Time 92
DATETIME 19 DATETIME java.sql.Timestamp 93
TIMESTAMP 19 TIMESTAMP java.sql.Timestamp 93
YEAR 4 YEAR java.sql.Date 91

3.3 BLOB类型

MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器(例如图片)

须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。

四种BLOB类型:

  1. TinyBlob 255B

  2. Blob 64KB

  3. MediumBlob 16MB

  4. LongBlob 4GB

// 操作Blob类型的变量 FileInputStream fis = new FileInputStream(filename); ps.setBlob(4, fis);

//读取Blob类型的字段 Blob blobname = rs.getBlob(5); InputStream is = blobname.getBinaryStream();

 

3.4 批量处理

JDBC的批量处理语句包括下面三个方法:

  • addBatch(String):添加需要批量处理的SQL语句或是参数;

  • executeBatch():执行批量处理语句;

  • clearBatch():清空缓存的数据

mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持

?rewriteBatchedStatements=true 写在配置文件的url后面

使用更新的mysql 驱动:mysql-connector-java-5.1.37-bin.jar

3.5 DAO

DAO:Data Access Object访问数据信息的类和接口,包括了对数据的CRUD(Create、Retrival、Update、Delete)

3.6 JDBC数据库连接池

3.6.1 概述

  • 普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码(得花费0.05s~1s的时间)。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。数据库的连接资源并没有得到很好的重复利用。

  • 对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。

  • 这种开发不能控制被创建的连接对象数, 系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。

  • 数据库连接池的基本思想:就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。

  • 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个

  • 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

  • 优点

    1. 资源重用

    由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。

    2. 更快的系统反应速度

    数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间

    3. 新的资源分配手段

    对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源

    4. 统一的连接管理,避免数据库连接泄漏

    在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露

3.6.2 使用

JDBC 的数据库连接池使用 javax.sql.DataSource

  • DBCP 是Apache提供的数据库连接池。tomcat 服务器自带dbcp数据库连接池。速度相对c3p0较快,但因自身存在BUG,Hibernate3已不再提供支持。

  • C3P0 是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以。hibernate官方推荐使用

  • Proxool 是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点

  • BoneCP 是一个开源组织提供的数据库连接池,速度快

  • Druid 是阿里提供的数据库连接池,据说是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池,但是速度不确定是否有BoneCP快

DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把 DataSource 称为连接池

DataSource用来取代DriverManager来获取Connection,获取速度快,同时可以大幅度提高数据库访问速度。

注意:

  • DataSource是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。

  • 数据库访问结束后关闭数据库连接:conn.close(); 并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。

1.C3P0
//使用C3P0数据库连接池的配置文件方式,获取数据库的连接:推荐
private static DataSource cpds = new ComboPooledDataSource("helloc3p0");
public static Connection getConnection2() throws SQLException{
Connection conn = cpds.getConnection();
return conn;
}

其中,src下的配置文件为:【c3p0-config.xml】

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="helloc3p0">
<!-- 获取连接的4个基本信息 -->
<property name="user">root</property>
<property name="password">abc123</property>
<property name="jdbcUrl">jdbc:mysql:///test</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>

<!-- 涉及到数据库连接池的管理的相关属性的设置 -->
<!-- 若数据库中连接数不足时, 一次向数据库服务器申请多少个连接 -->
<property name="acquireIncrement">5</property>
<!-- 初始化数据库连接池时连接的数量 -->
<property name="initialPoolSize">5</property>
<!-- 数据库连接池中的最小的数据库连接数 -->
<property name="minPoolSize">5</property>
<!-- 数据库连接池中的最大的数据库连接数 -->
<property name="maxPoolSize">10</property>
<!-- C3P0 数据库连接池可以维护的 Statement 的个数 -->
<property name="maxStatements">20</property>
<!-- 每个连接同时可以使用的 Statement 对象的个数 -->
<property name="maxStatementsPerConnection">5</property>

</named-config>
</c3p0-config>
2.DBCP

使用该连接池实现,应在系统中增加如下两个 jar 文件:

  • Commons-dbcp.jar:连接池的实现

  • Commons-pool.jar:连接池实现的依赖库

Tomcat 的连接池正是采用该连接池来实现的

  • 配置属性说明

属性默认值说明
initialSize 0 连接池启动时创建的初始化连接数量
maxActive 8 连接池中可同时连接的最大的连接数
maxIdle 8 连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负数表示不限制
minIdle 0 连接池中最小的空闲的连接数,低于这个数量会被创建新的连接。该参数越接近maxIdle,性能越好,因为连接的创建和销毁,都是需要消耗资源的;但是不能太大。
maxWait 无限制 最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间,超过该时间限制会抛出异常,如果设置-1表示无限等待
poolPreparedStatements false 开启池的Statement是否prepared
maxOpenPreparedStatements 无限制 开启池的prepared 后的同时最大连接数
minEvictableIdleTimeMillis   连接池中连接,在时间段内一直空闲, 被逐出连接池的时间
removeAbandonedTimeout 300 超过时间限制,回收没有用(废弃)的连接
removeAbandoned false 超过removeAbandonedTimeout时间后,是否进 行没用连接(废弃)的回收
  • 获取连接方式:

//使用dbcp数据库连接池的配置文件方式,获取数据库的连接:推荐
private static DataSource source = null;
static{
try {
Properties pros = new Properties();

InputStream is = DBCPTest.class.getClassLoader().getResourceAsStream("dbcp.properties");

pros.load(is);
//根据提供的BasicDataSourceFactory创建对应的DataSource对象
source = BasicDataSourceFactory.createDataSource(pros);
} catch (Exception e) {
e.printStackTrace();
}

}
public static Connection getConnection4() throws Exception {

Connection conn = source.getConnection();

return conn;
}

其中,src下的配置文件为:【dbcp.properties】

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true&useServerPrepStmts=false
username=root
password=abc123

initialSize=10
#...其他配置
3.Druid

Druid是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、Proxool等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池,可以说是目前最好的连接池之一。

package com.atguigu.druid;

import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSourceFactory;

public class TestDruid {
public static void main(String[] args) throws Exception {
Properties pro = new Properties(); pro.load(TestDruid.class.getClassLoader().getResourceAsStream("druid.properties"));
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
Connection conn = ds.getConnection();
System.out.println(conn);
}
}

其中,src下的配置文件为:【druid.properties】

url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver

initialSize=10
maxActive=20
maxWait=1000
filters=wall
  • 详细配置参数:

配置缺省说明
name   配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 如果没有配置,将会生成一个名字,格式是:”DataSource-” + System.identityHashCode(this)
url   连接数据库的url,不同数据库不一样。例如:mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
username   连接数据库的用户名
password   连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里:https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter
driverClassName   根据url自动识别 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下)
initialSize 0 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
maxActive 8 最大连接池数量
maxIdle 8 已经不再使用,配置了也没效果
minIdle   最小连接池数量
maxWait   获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
poolPreparedStatements false 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
maxOpenPreparedStatements -1 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
validationQuery   用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
testOnBorrow true 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testOnReturn false 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testWhileIdle false 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
timeBetweenEvictionRunsMillis   有两个含义: 1)Destroy线程会检测连接的间隔时间2)testWhileIdle的判断依据,详细看testWhileIdle属性的说明
numTestsPerEvictionRun   不再使用,一个DruidDataSource只支持一个EvictionRun
minEvictableIdleTimeMillis    
connectionInitSqls   物理连接初始化的时候执行的sql
exceptionSorter   根据dbType自动识别 当数据库抛出一些不可恢复的异常时,抛弃连接
filters   属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
proxyFilters   类型是List,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系

3.7 事务

事务(Transaction):是并发控制的单元,是用户定义的一个操作序列(具体概念见MySQL基础)本质上就是如何把多条SQL包裹在一个数据库事务中执行

事务通常是以begin transaction开始,以commit或rollback结束:

Commint表示提交,即提交事务的所有操作,正常结束

Rollback表示回滚,滚回到事务开始的状态

事务分类:

  • 自动提交事务:每条单独的语句都是一个事务。每个语句后都隐含一个commit。

  • 显式事务:以begin transaction显示开始,以commit或rollback结束

  • 隐式事务:无须描述事物的开始,只需显式提交或回滚每个事务

Connection conn = openConnection();
try {
   // 关闭自动提交:
   conn.setAutoCommit(false);
   // 执行多条SQL语句:
   insert(); update(); delete();
   // 提交事务:
   conn.commit();
} catch (SQLException e) {
   // 回滚事务:
   conn.rollback();
} finally {
   conn.setAutoCommit(true);
   conn.close();
}

// 设定隔离级别为READ COMMITTED:
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

基本步骤:

  1. 设置事务的提交方式为非自动提交:conn.setAutoCommit(false);

  2. 将需要添加事务的代码放入try catch块中。

  3. 在try块内添加事务的提交操作,表示操作无异常,提交事务。conn.commit();

  4. 在catch块内添加回滚事务,表示操作出现异常,撤销事务:conn.rollback();

  5. 设置事务提交方式为自动提交:conn.setAutoCommit(true);

4. DBUtils

Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。

DBUtils封装了JDBC的操作,Dbutils三个核心功能:

4.1 QueryRunner

该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。

方法说明
QueryRunner(DataSource ds) 传入参数为连接池,或无参构造
public int update(Connection conn, String sql, Object... params) 执行insert update delete操作
public Object query(Connection conn, String sql, ResultSetHandler rsh,Object... params) 执行 select查询操作

4.2 ResultSetHandler

用于定义select操作后,怎样封装结果集.

API说明
ArrayHandler 把结果集中的第一行数据转成对象数组
ArrayListHandler 把结果集中的每一行数据都转成一个对象数组,再存放到List中
BeanHandler 将结果集中的第一行数据封装到一个对应的JavaBean实例中
BeanListHandler 将结果集中的每一行数据封装到一个对应的JavaBean实例中,存放到List里
ColumnListHandler 将结果集中某一列的数据存放到List中
KeyedHandler 将结果集中的每一行数据都封装到一个Map里,然后再根据指定的key把每个Map再存放到一个Map里
MapHandler 将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。(用于查询单个)
MapListHandler 将结果集中的每一行数据都封装到一个Map里,然后再存放到List
ScalarHandler 将结果集中某一条记录的其中某一列的数据存成Object
QueryRunner 进行查询的操作
DbUtils 关闭链接等操作

4.3 DbUtils

提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的

  • public static void close(…) throws java.sql.SQLException:DbUtils类提供了三个重载的关闭方法

    这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。

  • public static void closeQuietly(…): 这一类方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLEeception

  • public static void commitAndClose(Connection conn)throws SQLException: 用来提交连接的事务,然后关闭连接

  • public static void commitAndCloseQuietly(Connection conn): 用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常

  • public static void rollback(Connection conn)throws SQLException:允许conn为null,因为方法内部做了判断

  • public static void rollbackAndClose(Connection conn)throws SQLException

  • rollbackAndCloseQuietly(Connection conn)

  • public static boolean loadDriver(java.lang.String driverClassName):这一方装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。

posted @ 2021-04-26 20:55  FremontUltimate  阅读(270)  评论(0)    收藏  举报