一、需求背景:

我们生活经常遇到一个情况:在购买商品的时候,已经支付的了,那么商品应该处于已购买订单里。而不是付款之后,已购买商品没有。

还有转账的时候,转出方和转入方都需要扣减相应的金额,而不是一方减少或者增加。

因为上面的例子都是对数据操作,所以需要我们操作数据库的事务。

如何确定一个事务范围?

事务是由一系列数据库操作组成,他和业务场景有关。当操作完成的时候,如果操作过程没有出现失败,则这个事务产生的数据库操作一并提交(commit)。反之,如果出现失败,则一并回滚(rollback)。

所有事务和业务层(service)确定。

事务的特点:

ACID

   1、原子性:事务里面的操作单元不可切割,要么全部成功,要么全部失败
        2、一致性:事务执行前后,业务状态和其他业务状态保持一致.
        3、隔离性:一个事务执行的时候最好不要受到其他事务的影响
        4、持久性:一旦事务提交或者回滚.这个状态都要持久化到数据库中

不考虑隔离性会出现的读问题:
        脏读:在一个事务中读取到另一个事务没有提交的数据
        不可重复读:在一个事务中,两次查询的结果不一致(针对的update操作)
        虚读(幻读):在一个事务中,两次查询的结果不一致(针对的insert操作)
    通过设置数据库的隔离级别来避免上面的问题(理解)
        read uncommitted      读未提交    上面的三个问题都会出现
        read committed      读已提交    可以避免脏读的发生
        repeatable read        可重复读    可以避免脏读和不可重复读的发生
        serializable        串行化        可以避免所有的问题

两种方式:

1)数据库上控制事务:

默认情况下,mysql数据库中的事务是自动提交。

 mysql> show variables like "%autocommit%";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
row in set (0.00 sec

我们可以在数据库上进行事务的开启和关闭。但是这种方式显然不好。

2)java代码实现。

查看connection的方法:

1:void commit() 提交事务。Makes all changes made since the previous commit/rollback permanent and releases any database locks currently held by this Connection object.

2:void  rollback()回滚事务.Undoes all changes made in the current transaction and releases any database locks currently held by this Connection object

3:void setAutocommit(boolean ) false 表示开启事务,true表示事务关闭。Sets this connection's auto-commit mode to the given state.

注意:事务要作用同一个数据库连接。

java代码实现有两种方式:

  1、自上到下传递参数:

    通过service传递到dao层的connection的变量,保证整个过程使用的是同一个数据连接。

  2、当前线程绑定事务:

    通过绑定当前线程一个变量(connection),在dao中获取这个connection,保证整个事务的过程中,使用的是同一个连接。

  其中threadLocal方法:ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID)

    该字段在类中要以private  static 来进行修饰。

    1) T  get() 返回当前线程绑定的值。

    2)void  remove() 从当前线程解绑。

    3)void  set(T  value)  绑定当前线程。

内部实现原理就是map方法对currentThread  进行put 和set  remove。

jdbc工具类:

 package jd.com.tool_jdbc;

 import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory; import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties; public class ds_tool {
private static BasicDataSource ds=null;
private static Connection con=null;
private static ThreadLocal<Connection> threadLocal=new ThreadLocal<>();
public static BasicDataSource getDs(){
try {
InputStream inp= ds_tool.class.getClassLoader().getResourceAsStream("database.properties");
Properties pro=new Properties();
pro.load(inp);
ds=new BasicDataSourceFactory().createDataSource(pro);
ds.setInitialSize();
ds.setMaxTotal();
ds.setMaxIdle();
return ds;
}catch (Exception ex){
throw new RuntimeException("初始化数据库失败"+ex);
} }
//给当前线程绑定变量。
public static BasicDataSource setDs(){
try {
if(con==null){
ds=getDs();
con=ds.getConnection();
threadLocal.set(con);
}else{
threadLocal.set(con);
}
return ds;
}catch (Exception ex){
ex.printStackTrace();
throw new RuntimeException("初始化错误"+ex);
} }
//开启事务
public static void openEven(){
try {
setDs();
con=threadLocal.get();
con.setAutoCommit(false);
}catch (Exception ex){
ex.printStackTrace();
} }
//提交事务
public static void commEven(){
try {
con=threadLocal.get();
con.commit();
}catch (Exception ex){
ex.printStackTrace();
} }
//回滚事务
public static void rollbackEvent(){
try {
con=threadLocal.get();
System.out.println(con);
con.rollback();
}catch (Exception ex){
ex.printStackTrace();
} }
public static void closedDs(BasicDataSource ds, PreparedStatement pre){
try {
ds.close();
pre.close();
threadLocal.remove();
}catch (Exception ex){
ex.printStackTrace();
} } }

然后在业务层上进行事务的控制。

3)1、queryRunner()初始化的时候,不带参数,是默认是开启事务。

  在执行的时候,update(connection con  sql  object ...parm)传入connection。需要关闭资源 connection。

  2、如果quryRunner(Datasource ds)的时候,内部代码会帮我们实现资源回收。不需要connection.close()

java操作数据库的事务支持的更多相关文章

  1. Java操作数据库——在JDBC里使用事务

    Java操作数据库——在JDBC里使用事务 摘要:本文主要学习了如何在JDBC里使用事务. 使用Connection的事务控制方法 当JDBC程序向数据库获得一个Connection对象时,默认情况下 ...

  2. Java操作数据库——使用连接池连接数据库

    Java操作数据库——使用连接池连接数据库 摘要:本文主要学习了如何使用JDBC连接池连接数据库. 传统方式和连接池方式 传统方式的步骤 使用传统方式在Java中使用JDBC连接数据库,完成一次数据库 ...

  3. Java操作数据库——使用JDBC连接数据库

    Java操作数据库——使用JDBC连接数据库 摘要:本文主要学习了如何使用JDBC连接数据库. 背景 数据持久化 数据持久化就是把数据保存到可掉电式存储设备中以供之后使用.大多数情况下,特别是企业级应 ...

  4. Java操作属性文件,支持新增或更新多个属性

    Java操作属性文件.支持新增或更新多个属性 一.更新或新增单个属性的方法 /** * 写入properties信息 * @param filePath 绝对路径(包含文件名称和后缀名) * @par ...

  5. java操作数据库:增删改查

    不多bb了直接上. 工具:myeclipse 2016,mysql 5.7 目的:java操作数据库增删改查商品信息 test数据库的goods表 gid主键,自增 1.实体类Goods:封装数据库数 ...

  6. JDBC 数据库连接 Java操作数据库 jdbc快速入门

    JDBC基本概念 Java DataBase Connectivity 数据库连接 java操作数据库 本质上(sun公司的程序员)定义的一套操作关系型数据库的规则 既接口  更新内容之前 代码 pa ...

  7. JDBC数据源(DataSource)数据源技术是Java操作数据库的一个很关键技术,流行的持久化框架都离不开数据源的应用。

    JDBC数据源(DataSource)的简单实现   数据源技术是Java操作数据库的一个很关键技术,流行的持久化框架都离不开数据源的应用. 2.数据源提供了一种简单获取数据库连接的方式,并能在内部通 ...

  8. Java操作数据库——手动实现数据库连接池

    Java操作数据库——手动实现数据库连接池 摘要:本文主要学习了如何手动实现一个数据库连接池,以及在这基础上的一些改进. 部分内容来自以下博客: https://blog.csdn.net/soonf ...

  9. JDBC 4.0 开始Java操作数据库不用再使用 Class.forName加载驱动类了

    JDBC 4.0 开始Java操作数据库不用再使用 Class.forName加载驱动类了 代码示例 转自 https://docs.oracle.com/javase/tutorial/jdbc/o ...

随机推荐

  1. OSGI企业应用开发(十二)OSGI Web应用开发(一)

    前面文章中介绍了如何在OSGI应用中整合Spring和Mybatis框架,本篇文章开始介绍如何使用OSGI技术开发Web应用.对于传统的Java EE应用,应用中涉及到的Web元素无非就是Servle ...

  2. SQLServer SQL连接查询深度探险(摘录

    SQL连接查询深度探险[摘录] 测试环境: Windows XP Profession MySQL 5.0.45 Oracle 9i DB2 UDB 9.1 测试的SQL脚本如下:此脚本适合MySQL ...

  3. Android 系统中运行jar文件

    在android系统中运行jar操作步骤: 1.       打包编译jar包 2.       将jar包导入android设备中 adb push test.jar  /data/local/tm ...

  4. 安装 Java 开发工具包JDK(Windows版本)

    前言: 进行java开发,首先要安装jdk,安装完成之后,还需要进行环境变量配置,以下就介绍一下具体步骤 具体步骤: 1.进入官网(https://www.oracle.com/technetwork ...

  5. ubuntu更新下载源问题

    Q1:ubuntu14.04系统安装完之后无法跟新并安装插件 cd /var/lib/apt/lists sudo rm * -rf sudo apt-get clean;sudo apt-get u ...

  6. Android 监听手机GPS打开状态

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/70854942 本文出自[赵彦军的博客] GPS_Presenter package ...

  7. springcloud 入门 2 (Enreka的服务和注册)

    spring cloud eureka: eureka 用以服务发现.服务注册,比较流行的有consul(后面再介绍) eureka介绍: eureka为netflix开源软件,分为三个部分: eur ...

  8. git中设置代理,本地不使用代理,针对域名设置代理

    想要的效果是: [1]本地IP不使用代理 [2]外网的仓库(如GitHub)使用代理 [3]适用于全局 方案 打开路径: C --> 用户 --> [我的账号] --> .gitco ...

  9. md5sum 和 sha256sum用于 验证软件完整性

    md5sum 和 sha256sum 都用来用来校验软件安装包的完整性,本次我们将讲解如何使用两个命令进行软件安装包的校验: sha 是什么?        sha 为 安全散列算法(英语:Secur ...

  10. 【汇编】SI DI 的用法

    一.汇编语言中,为什么SI和DI不能同时使用汇编 其实你可以想一下,这两个寄存器的意思,SI源变址寄存器,DI目地变址寄存器,既然是变址寄存器,那么他们肯定是在某个地址的基础上进行偏移变化,由此我们就 ...