JDBC、数据库连接池以及事务的基本概念与使用

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: JDBC、数据库连接池以及事务的基本概念与使用

1 关于JDBC


JDBC 全称为:Java DataBase Connectivity,它是可以执⾏SQL 语句的Java API。由Sun公司提供接口,数据库厂商负责实现,在使用不同数据库时,只要用数据库厂商提供的数据库驱动程序即可,大大简化学习成本。


1.1 步骤

  1. 导⼊MySQL或者Oracle驱动包,添加到路径
  2. 装载数据库驱动程序
  3. 获取到与数据库连接
  4. 获取可以执⾏SQL 语句的对象
  5. 执⾏SQL 语句
  6. 关闭连接


//简单示例
Class.forName(come.mysql.jdbc.Driver);
String username="root";
String password="123456";
String connectUrl="jdbc:mysql://127.0.0.1:3306/db_test?useUnicode=true&characterEncodeing=UTF-8";
Connection conn=DriverManager.getConnection(connectionUrl,username,password);
System.out.println("连接成功");
conn.close();
system.out.println("关闭连接");


1.2 Connection 对象

客户端与数据库所有的交互都是通过Connection 来完成的。常用方法如下:


//创建向数据库发送sql 的statement对象。
createcreateStatement ()
//创建向数据库发送预编译sql 的PrepareSatement对象。
prepareStatement (sql ) 
//创建执⾏存储过程的callableStatement对象
prepareCall (sql )
//设置事务⾃动提交
setAutoCommit (boolean autoCommit)
//提交事务
commit ()
//回滚事务
rollback (


1.3 Statement对象

Statement对象⽤于向数据库发送Sql语句,对数据库的增删改查都可以通过此对象发送sql语句完成,方法如下:


//查询
executeQuery(String  sql )
//增删改
executeUpdate (String  sql )
//任意sql 语句都可以,但是⽬标不明确,很少⽤
execute(String  sql )
//把多条的sql 语句放进同⼀个批处理中
addBatch (String  sql )
//向数据库发送⼀批sql 语句执⾏
executeBatch()

 


PreparedStatement对象

PreparedStatement 对象继承Statement对象,它⽐Statement对象更强⼤,使⽤起来更简单


  1. Statement 对象编译SQL 语句时,如果SQL 语句有变量,就需要使⽤分隔符来隔开,如果变量⾮常多,就会使SQL 变得⾮常复杂。PreparedStatement 可以使⽤占位符,简化sql的编写
  2. Statement 会频繁编译SQL 。PreparedStatement 可对SQL 进⾏预编译,提⾼效率,预编译的SQL 存储在PreparedStatement 对象中
  3. PreparedStatement 防⽌SQL 注⼊。【Statement 通过分隔符’++’, 编写永等式,可以不需要密码就进⼊数据库】


//模拟查询id为2的信息
         String  id = "2" ;
         Connection connection = UtilsDemo.getConnection ();
         String  sql  = "SELECT * FROM users WHERE id = ?";
         PreparedStatement preparedStatement = 
connection.preparedStatement(sql );
         //第⼀个参数表示第⼏个占位符【也就是?号】,第⼆个参数表示值是多少
         preparedStatement.setString(1,id);
         ResultSet resultSet = preparedStatement.executeQuery()
              //模拟查询id为2的信息
         String  id = "2" ;
         Connection connection = UtilsDemo.getConnection ();
         String  sql  = "SELECT * FROM users WHERE id = ?";
         PreparedStatement preparedStatement = 
connection.preparedStatement(sql );
         //第⼀个参数表示第⼏个占位符【也就是?号】,第⼆个参数表示值是多少
         preparedStatement.setString(1,id);
         ResultSet resultSet = preparedStatement.executeQuery()


1.4 ResultSet对象

ResultSet 对象代表Sql语句的执⾏结果,当Statement 对象执⾏executeQuery()时,会返回⼀个ResultSet对象

ResultSet对象维护了⼀个数据⾏的游标【简单理解成指针】,调用ResultSet.next()⽅法,可以让游标指向具体的数据⾏,进⾏获取该⾏的数据。


1.5 MetaData元数据

对列字段的描述信息,在结果集中,不但由每一行的数据,还有元数据信息。包括列名、列标题、列类型等。对于增删改⽽⾔,只有SQL 和参数是不同的,我们为何不把这些相同的代码抽取成⼀个⽅法?对于查询⽽⾔,不同的实体查询出来的结果集是不⼀样的。我们要使⽤元数据获取结果集的信息,才能对结果集进⾏操作。


  • ParameterMetaData – 参数的元数据
  • ResultSetMetaData --结果集的元数据
  • DataBaseMetaData --数据库的元数据


2 数据库连接池


数据库的连接的建⽴和关闭是⾮常消耗资源的、频繁地打开、关闭连接造成系统性能低下。


2.1 认识JDBC连接

每一个JDBC连接,内部实现上是创建了一个TCP/Socket连接。在MySQL中可以查看连接的情况。一个连接上可以执行多次SQL交互,连接要及时关闭,否则会导致连接量过大,到达上限后便不会接收新的连接。


SHOW STATUS LIKE 'Threads%' /*连接数量*/
SHOW processlist  /*连接详情*/
SHOW full processlist
SHOW VARIABLES LIKE 'max_connections' /*查看最大连接数*/


连接超时:当一个连接到MySQL之后,如果长时间未作任何SQL交互,会被认定超时而断开。其中,wait_timeout即为超时时间的设定


SHOW GLOBAL VARIABLES LIKES '%timeout%'


2.2 连接效率

JDBC两种连接方式:


  • 短连接方式:需要时连接,用完了就关闭。

优点:容易管理

缺点:连接费时,运行效率低


  • 长连接方式:准备好一个连接,需要的时候就用,用完了不关闭。

优点:运行效率高

缺点:管理困难,在多线程环境下,并发难以处理。


2.3 c3p0连接池库

//一个DataSource指代一个数据源,内部有一个连接池,自动读取c3p0-config.xml的配置
ComboPooledDataSource pool=new ComboPooledDataSource();
//一个connection代表一次访问
Connection conn=pool.getConnection();
//下面建立statement对象,通过查询生成ResultSet
//用完之后
conn.close();//连接放回池子
pool.close();


  1. 池子中取得的connection,在取出之前就已经通过用户名密码验证,可以直接使用。
  2. 当conn.close()时,并没有关闭底层的socket连接,仅仅是把这个连接放回池子里。
  3. 连接池一般创建为全局对象(public static),多个线程可以并发使用。


3 Transaction事务


一个业务单元:需要一次性地执行多个SQL操作,修改多个有关系的表。


事务的一般使用模式:


beginTrasaction();//开始事务
try{
    sql1;
    sql2;
    sql3;
    commit()//提交,确认所有修改
}catch(e){
rollback()  //回滚,撤销所有修改
}


  1. 原子性(Atomicity)

事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。

回滚可以用日志来实现,日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。


  1. 一致性(Consistency)

数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对一个数据的读取结果都是相同的。


  1. 隔离性(Isolation)

一个事务所做的修改在最终提交以前,对其它事务是不可见的。


  1. 持久性(Durability)

一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。

可以通过数据库备份和恢复来实现,在系统发生奔溃时,使用备份的数据库进行数据恢复。


3.2 事务的使用

举例:A向B转账,转账这个流程中如果出现问题,事务可以让数据恢复成⼀样【A账户的钱没变,B账户的钱也没变】。


/*
    * 我们来模拟A向B账号转账的场景
    *   A和B账户都有1000块,现在我让A账户向B账号转500 块钱
    *
    * */
            //JDBC默认的情况下是关闭事务的,下⾯我们看看关闭事务去操作转账操作有什么问题
            //A 账户减去500 块
            String  sql  = "UPDATE a SET money=money-500 " ;
            preparedStatement = connection.prepareStatement (sql );
            preparedStatement.executeUpdate ();
            //B 账户多了500 块
            String  sql2 = "UPDATE b SET money=money+500";
            preparedStatement = connection.prepareStatement (sql2);
            preparedStatement.executeUpdate ();


模拟出现问题的情况,显然,上⾯代码是会抛出异常的,我们再来查询⼀下数据。A账户少了500 块钱,B账户的钱没有增加。这明显是不合理的。


//A 账户减去500 块
            String  sql  = "UPDATE a SET money=money-500 " ;
            preparedStatement = connection.prepareStatement (sql );
            preparedStatement.executeUpdate ();
      //这⾥模拟出现问题
            int  a = 3 / 0;
            String  sql2 = "UPDATE b SET money=money+500";
            preparedStatement = connection.prepareStatement (sql2);
            preparedStatement.executeUpdate ();


通过事务解决上面的问题


//开启事务,对数据的操作就不会⽴即⽣效。
            connection.setAutoCommit (false);
            //A 账户减去500 块
            String  sql  = "UPDATE a SET money=money-500 " ;
            preparedStatement = connection.prepareStatement (sql );
            preparedStatement.executeUpdate ();
            //在转账过程中出现问题
            int  a = 3 / 0;
            //B 账户多500 块
            String  sql2 = "UPDATE b SET money=money+500";
            preparedStatement = connection.prepareStatement (sql2);
            preparedStatement.executeUpdate ();
            //如果程序能执⾏到这⾥,没有抛出异常,我们就提交数据
            connection.commit ();
      //关闭事务【⾃动提交】
      connection.setAutoCommit (true);
        } catch (SQLException e) {
            try  {
                 //如果出现了异常,就会进到这⾥来,我们就把事务回滚【将数据变成原来那样】
                 connection.rollback ();
      //关闭事务【⾃动提交】
                 connection.setAutoCommit (true);
            } catch (SQLException e1) {
                 e1.printStackTrace();
            }


上⾯的程序也⼀样抛出了异常,A账户钱没有减少,B账户的钱也没有增加。

注意:当Connection遇到⼀个未处理的SQLException时,系统会⾮正常退出,事务也会⾃动回滚,但如果程序捕获到了异常,是需要在catch 中显式回滚事务的.


3.3 事务的隔离级别

数据库定义了4个隔离级别:


  1. Serializable【可避免脏读,不可重复读,虚读】
  2. Repeatable read 【可避免脏读,不可重复读】
  3. Read committed 【可避免脏读】
  4. Read uncommitted 【级别最低,什么都避免不了】


分别对应Connection类中的4个常量


  1. TRANSACTION_READ_UNCOMMITTED
  2. TRANSACTION_READ_COMMITTED
  3. TRANSACTION_REPEATABLE_READ
  4. TRANSACTION_SERIALIZABLE


脏读:一个事务读取到另外一个事务未提交的数据


不可重复读:⼀个事务读取到另外⼀个事务已经提交的数据,也就是说⼀个事务可以看到其他事务所做的修改


虚读(幻读):是指在⼀个事务内读取到了别的事务插⼊的数据,导致前后读取不⼀致。注:和不可重复读类似,但虚读(幻读)会读到其他事务的插⼊的数据,导致前后读取不⼀致


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
11天前
|
Java 关系型数据库 数据库连接
实时计算 Flink版操作报错之在使用JDBC连接MySQL数据库时遇到报错,识别不到jdbc了,怎么解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
12天前
|
SQL 关系型数据库 MySQL
使用关系型数据库事务的例子
【5月更文挑战第12天】本文介绍了设置MySQL事务的三种方式:全局、当前session和下一个事务,并提供了示例代码展示如何开始事务和设置隔离级别。还简述了引擎设置和数据源DSN格式。最后,讨论了SQL优化策略,包括选择合适的存储引擎、优化字段数据类型、建立索引、避免全表扫描等。
36 4
使用关系型数据库事务的例子
|
12天前
|
存储 关系型数据库 MySQL
了解如何在关系型数据库中处理事务
【5月更文挑战第12天】数据库事务确保数据的ACID特性,即原子性、一致性、隔离性和持久性。它们用于一组操作,要么全部成功,要么全部不执行,防止数据不一致。MySQL的InnoDB存储引擎严格支持事务。MySQL默认隔离级别为REPEATABLE READ
41 3
|
3天前
|
存储 关系型数据库 数据库
不直接使用文件存储?浅谈数据库的三级模式及重要概念
【5月更文挑战第21天】本文介绍数据库用于解决传统文件系统如Excel的数据冗余、不一致性和访问困难等问题。关系型数据库通过DBMS实现数据管理,包括外模式(用户视图)、概念模式(全局逻辑结构)和内模式(物理存储)。
18 1
不直接使用文件存储?浅谈数据库的三级模式及重要概念
|
6天前
|
存储 安全 关系型数据库
理解数据库事务的用处
【5月更文挑战第18天】数据库事务确保数据ACID特性,即原子性、一致性、隔离性和持久性。事务控制通过原子性保证操作全做或全不做,一致性维护数据完整性,隔离性防止并发问题,持久性确保提交后变更永久。事务故障恢复通过逆操作撤销,系统故障恢复在重启时自动重做或撤销事务。介质故障和病毒破坏需结合备份和日志恢复。检查点技术加速恢复,记录检查点时的事务清单和日志地址。
23 0
理解数据库事务的用处
|
7天前
|
安全 Java 数据库连接
Pivotal Greenplum JDBC在数据库开启ssl后url如何编辑
【5月更文挑战第23天】Pivotal Greenplum JDBC在数据库开启ssl后url如何编辑
35 8
|
10天前
|
SQL Java 关系型数据库
JavaWeb(JDBC编程)看这一篇就够了 —— 如何使用Java操作mysql数据库
JavaWeb(JDBC编程)看这一篇就够了 —— 如何使用Java操作mysql数据库
9 0
|
10天前
|
SQL Java 关系型数据库
Java之JDBC数据库编程
Java之JDBC数据库编程
13 2
|
16天前
|
Java 数据处理 流计算
实时计算 Flink版产品使用合集之可以通过JDBC连接器来连接Greenplum数据库吗
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
28 1
|
18天前
|
存储 数据采集 数据管理
什么是数据库的概念模式
什么是数据库的概念模式
33 5