java操作数据库的事务支持
一、需求背景:
我们生活经常遇到一个情况:在购买商品的时候,已经支付的了,那么商品应该处于已购买订单里。而不是付款之后,已购买商品没有。
还有转账的时候,转出方和转入方都需要扣减相应的金额,而不是一方减少或者增加。
因为上面的例子都是对数据操作,所以需要我们操作数据库的事务。
如何确定一个事务范围?
事务是由一系列数据库操作组成,他和业务场景有关。当操作完成的时候,如果操作过程没有出现失败,则这个事务产生的数据库操作一并提交(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操作数据库的事务支持的更多相关文章
- Java操作数据库——在JDBC里使用事务
Java操作数据库——在JDBC里使用事务 摘要:本文主要学习了如何在JDBC里使用事务. 使用Connection的事务控制方法 当JDBC程序向数据库获得一个Connection对象时,默认情况下 ...
- Java操作数据库——使用连接池连接数据库
Java操作数据库——使用连接池连接数据库 摘要:本文主要学习了如何使用JDBC连接池连接数据库. 传统方式和连接池方式 传统方式的步骤 使用传统方式在Java中使用JDBC连接数据库,完成一次数据库 ...
- Java操作数据库——使用JDBC连接数据库
Java操作数据库——使用JDBC连接数据库 摘要:本文主要学习了如何使用JDBC连接数据库. 背景 数据持久化 数据持久化就是把数据保存到可掉电式存储设备中以供之后使用.大多数情况下,特别是企业级应 ...
- Java操作属性文件,支持新增或更新多个属性
Java操作属性文件.支持新增或更新多个属性 一.更新或新增单个属性的方法 /** * 写入properties信息 * @param filePath 绝对路径(包含文件名称和后缀名) * @par ...
- java操作数据库:增删改查
不多bb了直接上. 工具:myeclipse 2016,mysql 5.7 目的:java操作数据库增删改查商品信息 test数据库的goods表 gid主键,自增 1.实体类Goods:封装数据库数 ...
- JDBC 数据库连接 Java操作数据库 jdbc快速入门
JDBC基本概念 Java DataBase Connectivity 数据库连接 java操作数据库 本质上(sun公司的程序员)定义的一套操作关系型数据库的规则 既接口 更新内容之前 代码 pa ...
- JDBC数据源(DataSource)数据源技术是Java操作数据库的一个很关键技术,流行的持久化框架都离不开数据源的应用。
JDBC数据源(DataSource)的简单实现 数据源技术是Java操作数据库的一个很关键技术,流行的持久化框架都离不开数据源的应用. 2.数据源提供了一种简单获取数据库连接的方式,并能在内部通 ...
- Java操作数据库——手动实现数据库连接池
Java操作数据库——手动实现数据库连接池 摘要:本文主要学习了如何手动实现一个数据库连接池,以及在这基础上的一些改进. 部分内容来自以下博客: https://blog.csdn.net/soonf ...
- JDBC 4.0 开始Java操作数据库不用再使用 Class.forName加载驱动类了
JDBC 4.0 开始Java操作数据库不用再使用 Class.forName加载驱动类了 代码示例 转自 https://docs.oracle.com/javase/tutorial/jdbc/o ...
随机推荐
- Vue:v-on自定义事件
Vue中父组件使用prop向子组件传递数据,那么子组件向父组件使用什么方式传递信息:自定义事件. 1.先来看官网上面教程 每个 Vue 实例都实现了事件接口,即: 使用 $on(eventName) ...
- 记一次Full GC问题的排查
今天看到监控平台显示项目的Full GC次数过多,查看了一下监控曲线,如下图,发现发生的时间点基本上都是在上午十点之后,到下午五点. 分析:考虑到业务形态,开始初步怀疑是访问人数增多引起的虚拟机内存不 ...
- 设计模式(12)--Proxy(代理模式)--结构型
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.模式定义: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. ...
- CSS3实现的几个小loading效果
昨晚上闲的没事突然想做几个小loading效果,下面是昨晚上做的几个小案例,分享给大家 1.水波loading:这个loading是我觉得非常简单,但是看上去的效果却非常不错的一个小loading 这 ...
- framework7中a标签没反应
试试在a标签上加这个样式: class="external"
- Android项目实战(三十):Fresco加载gif图片并播放
前言: 项目中图文混合使用的太多太多了,但是绝大部分都是静态图片. 然而项目开发中有这么一个需求:显示一个出一个简短的动画(一般都不超过3秒)演示 比如说:一个功能提供很多步骤来教用户做广播体操,那么 ...
- Flutter 数据模型创建
build_runner的使用 1.在根目录运行 2.一次性创建.g.dart文件 使用build 此时目录内不能有.g.dart文件 3.watch是监听 有model类的文件创建 自动创建.g.d ...
- Vue入门系列(五)Vue实例详解与生命周期
Vue官网: https://cn.vuejs.org/v2/guide/forms.html#基础用法 [入门系列] (一) http://www.cnblogs.com/gdsblog/p/78 ...
- Django Forms实例
# Django的Form主要具有一下几大功能: # # 生成HTML标签 # 验证用户数据(显示错误信息) # HTML Form提交保留上次提交数据 # 初始化页面显示内容 # forms组件生成 ...
- Azure 门户中基于角色的访问控制入门
面向安全的公司应侧重于向员工提供他们所需的确切权限. 权限过多,可能会向攻击者公开帐户. 权限太少意味着员工无法有效地完成其工作. Azure 基于角色的访问控制 (RBAC) 可通过为 Azure ...