这是我JDBC的第一篇

http://blog.csdn.net/hon_3y/article/details/53535798

这是我JDBC的第二篇
http://blog.csdn.net/hon_3y/article/details/53725446


1.事务

一个SESSION所进行的所有更新操作要么一起成功,要么一起失败

举个例子: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向B转账,成功了。可是如果A向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();

显然,上面代码是会抛出异常的,我们再来查询一下数据。A账户少了500块钱,B账户的钱没有增加这明显是不合理的


我们可以通过事务来解决上面出现的问题

//开启事务,对数据的操作就不会立即生效。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中显式回滚事务的。


savapoint

我们还可以使用savepoint设置中间点。如果在某地方出错了,我们设置中间点,回滚到出错之前即可。

应用场景:现在我们要算一道数学题,算到后面发现算错数了。前面的运算都是正确的,我们不可能重头再算【直接rollback】,最好的做法就是在保证前面算对的情况下,设置一个保存点。从保存点开始重新算。

注意:savepoint不会结束当前事务,普通提交和回滚都会结束当前事务的


事务的隔离级别

数据库定义了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

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

例子:A向B转账,A执行了转账语句,但A还没有提交事务,B读取数据,发现自己账户钱变多了!B跟A说,我已经收到钱了。A回滚事务【rollback】,等B再查看账户的钱时,发现钱并没有多。


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

注:A查询数据库得到数据,B去修改数据库的数据,导致A多次查询数据库的结果都不一样【危害:A每次查询的结果都是受B的影响的,那么A查询出来的信息就没有意思了】


虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。

注:和不可重复读类似,但虚读(幻读)会读到其他事务的插入的数据,导致前后读取不一致


简单总结:脏读是不可容忍的,不可重复读和虚读在一定的情况下是可以的【做统计的肯定就不行】


2.元数据

什么是元数据

元数据其实就是数据库,表,列的定义信息

为什么我们要用元数据

即使我们写了一个简单工具类,我们的代码还是非常冗余。对于增删改而言,只有SQL和参数是不同的,我们为何不把这些相同的代码抽取成一个方法?对于查询而言不同的实体查询出来的结果集是不一样的。我们要使用元数据获取结果集的信息,才能对结果集进行操作

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

3.改造JDBC工具类

问题:我们对数据库的增删改查都要连接数据库,关闭资源,获取PreparedSteatment对象,获取Connection对象此类的操作,这样的代码重复率是极高的,所以我们要对工具类进行增强

增删改

//我们发现,增删改只有SQL语句和传入的参数是不知道的而已,所以让调用该方法的人传递进来//由于传递进来的参数是各种类型的,而且数目是不确定的,所以使用Object[]public static void update(String sql, Object[] objects) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {connection = getConnection();preparedStatement = connection.prepareStatement(sql);//根据传递进来的参数,设置SQL占位符的值for (int i = 0; i < objects.length; i++) {preparedStatement.setObject(i + 1, objects[i]);}//执行SQL语句preparedStatement.executeUpdate();} catch (Exception e) {e.printStackTrace();

查询

/*1:对于查询语句来说,我们不知道对结果集进行什么操作【常用的就是把数据封装成一个Bean对象,封装成一个List集合】2:我们可以定义一个接口,让调用者把接口的实现类传递进来3:这样接口调用的方法就是调用者传递进来实现类的方法。【策略模式】*///这个方法的返回值是任意类型的,所以定义为Object。public static Object query(String sql, Object[] objects, ResultSetHandler rsh) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {connection = getConnection();preparedStatement = connection.prepareStatement(sql);//根据传递进来的参数,设置SQL占位符的值if (objects != null) {for (int i = 0; i < objects.length; i++) {preparedStatement.setObject(i + 1, objects[i]);}}resultSet = preparedStatement.executeQuery();//调用调用者传递进来实现类的方法,对结果集进行操作return rsh.hanlder(resultSet);}

接口:

/** 定义对结果集操作的接口,调用者想要对结果集进行什么操作,只要实现这个接口即可* */public interface ResultSetHandler {Object hanlder(ResultSet resultSet);}

实现类:

//接口实现类,对结果集封装成一个Bean对象
public class BeanHandler implements ResultSetHandler {//要封装成一个Bean对象,首先要知道Bean是什么,这个也是调用者传递进来的。private Class clazz;public BeanHandler(Class clazz) {this.clazz = clazz;}@Overridepublic Object hanlder(ResultSet resultSet) {try {//创建传进对象的实例化Object bean = clazz.newInstance();if (resultSet.next()) {//拿到结果集元数据ResultSetMetaData resultSetMetaData = resultSet.getMetaData();for (int i = 0; i < resultSetMetaData.getColumnCount(); i++) {//获取到每列的列名String columnName = resultSetMetaData.getColumnName(i+1);//获取到每列的数据String columnData = resultSet.getString(i+1);//设置Bean属性Field field = clazz.getDeclaredField(columnName);field.setAccessible(true);field.set(bean,columnData);}//返回Bean对象return bean;}

转载于:https://www.cnblogs.com/zhong-fucheng/p/7203065.html

JDBC第三篇--【事务、元数据、改造JDBC工具类】相关推荐

  1. JDBC(本质,配置环境变量,JDBC编程六步,类加载注册,sql注入,事务问题,封装工具类,悲观锁,乐观锁)

    JDBC 2021.5.21 依然跟着动力节点杜老师学!!! 1.什么是JDBC? Java DataBase Connectivity 在java语言中编写sql语句,对mysql数据库中的数据进行 ...

  2. 三个好用的并发工具类

    转载自  三个好用的并发工具类 以前的文章中,我们介绍了太多的底层原理技术以及新概念,本篇我们轻松点,了解下 Java 并发包下.基于这些底层原理的三个框架工具类. 它们分别是: 信号量 Semaph ...

  3. JDBC批量增加批量修改增删改查工具类

    JDBC工具类 package com.belle.infrastructure.util;import java.sql.Connection; import java.sql.PreparedSt ...

  4. java druid jdbc例子_JDBC【使用Druid连接数据库,DBUtils工具类的使用】

    Druid连接数据库,DBUtils工具类的使用 1.在maven中添加Druid依赖 com.alibaba druid 1.2.0 2.封装Druid连接方法 import com.alibaba ...

  5. C# 之多线程篇 Task(C#超级工具类)

    在.NET 4.0中,并行计算与多线程得到了一定程度的加强,这主要体现在并行对象Parallel,多线程Task,与PLinq.这里对这些相关的特性一起总结一下.使用Thread方式的线程无疑是比较麻 ...

  6. 【工具篇】java导出excel工具类,多种模式自动配置,绝对值得你收藏

    文章目录 项目环境: 实现功能: 工具类实现 定义参数bean:ExportExcelBean.java 定义导出excel的表格主题:ExportExcelTheme.java [重点]导出exce ...

  7. 【工具篇】java导入excel工具类,简单通用,绝对值得你收藏

    定义导入的excel模板 定义需要导入的EXCEL模板,EXCEL格式变更,只需要变更对应的枚举信息就可以,如果定义多个EXCEL模板, 只要定义多个枚举就行 package org.util.exc ...

  8. jdbc连接mysql工具类_jdbc之工具类DBUtil的使用

    首先回顾一下jdbc的使用方法: 1. 注册驱动 2. 建立连接 3. 建立statement 4. 定义sql语句 5. 执行sql语句,如果执行的是查询需遍历结果集 6. 关闭连接 其中建立连接和 ...

  9. 短链接的生成之工具类的编写--三种方式(亲测可用)

    在很多时候我们都需要使用到短链接,比较常见的是在生成微信二维码的时候,长的url不能生成二维码,必须使用短链接.所以短链接的生成就尤其重要,废话不多说,下面直接介绍三种生成短链接的工具类 一.使用百度 ...

  10. 【MySQL从小白到高手】第六篇:事务和MySQL中的JDBC编程

    前言 目录 事务~ 什么是事务~ 事务的原子性~ 事务相关的面试题~ 脏读~ 不可重复读~ 幻读~ MySQL中事务的隔离级别~ MySQL中的JDBC编程~ JDBC~ 学习使用JDBC编程~ 引入 ...

最新文章

  1. RabbitMQ基础概念详细介绍
  2. Java 把一个InputStream转换为一个BufferedReader
  3. java延时执行_Java谓词的延迟执行
  4. The temporary upload location [/tmp/tomcat.xxx/work/Tomcat/localhost/etc] is not valid
  5. DEDE的简略标题标签的使用问题
  6. 动词ing基本用法_哪些动词后面只能接动名词背诵口诀
  7. 配置 Linux 的访问控制列表(ACL)
  8. PCL之积分图法线估计
  9. 使用FileWriter向文本文件中写信息
  10. 阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第3节 线程同步机制_4_解决线程安全问题_同步代码块...
  11. SSCOM下载及无法打开问题解决
  12. QTP教程入门到高级(转)
  13. abab的四字成语_带abab的四字成语大全
  14. snort:Packet结构体详解(留坑)
  15. ADSL拨号工作原理
  16. 2018东北四省赛参赛总结
  17. mysql自增不连续的问题 ALTER TABLE `表名` AUTO_INCREMENT =1;
  18. 微信扫码登录_JAVA
  19. C语言图书管理系统[2023-01-06]
  20. Vue 移动端项目创建

热门文章

  1. 最大团问题和最大独立子集
  2. mac phpstorm配置svn
  3. axure实现复选框全选_表格设置一键全选按钮,这样的打√方式,只需要三步搞定...
  4. 基于SSM的超市积分管理系统
  5. python3语法学习第四天--字符串
  6. Springboot中常用的注解
  7. 获取本地文件所需配置
  8. linux文件权限中 chmod、u+x、u、r、w、x分别代表什么
  9. 分表用到的一些函数/php mysql 前面补0
  10. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第1节 常用函数接口_8_常用的函数式接口_Supplier接口...