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 ...
随机推荐
- RocketMQ 消息存储
消息存储 主要的存储文件: 1.消息文件(commitLog) 2.消息消费队列文件(consumeQueue) 3.Hash索引文件(IndexFile) 4.检测点文件(checkpoint) 5 ...
- django 参考
1. 路由系统 https://www.cnblogs.com/maple-shaw/articles/9282718.html 2. 视图 https://www.cnblogs.com/maple ...
- django—xadmin中集成富文本编辑器ueditor
一.安装 pip命令安装,由于ueditor为百度开发的一款富文本编辑框,现已停止维护,如果解释器为python2,则直接pip install djangoueditor 解压包安装,python3 ...
- 关于ajax 传递的参数
ajax 发送的数据,默认都是字符串,不能直接传递list(列表),或者dict(字典). 若要 传递list(列表),或者dict(字典),需要进行一些操作. list 需要进行列表序列化,在aja ...
- Nginx的虚拟主机
1.虚拟主机的概念和类型 1.1 概念: 所谓的虚拟主机,在web服务里面就是一个独立的网站站点,这个站点对应独立的域名(也有可能是IP或者端口),具有独立的程序和资源目录,可以独立的对外提供服务. ...
- Oracle 修改oracle数据库名
Oracle 修改oracle数据库名 by:授客 QQ:1033553122 1.确保你有个可用于数据库恢复的,完整的数据库备份 2.确保数据库处于mount,非open状态,并且在加载前先以imm ...
- Python网络爬虫笔记(一):网页抓取方式和LXML示例
(一) 三种网页抓取方法 1. 正则表达式: 模块使用C语言编写,速度快,但是很脆弱,可能网页更新后就不能用了. 2. Beautiful Soup 模块使用Python编写,速度慢. ...
- 从零自学Java-7.使用数组存储信息
1.创建数组: 2.设置数组的大小: 3.为数组元素赋值: 4.修改数组中的信息: 5.创建多维数组: 6.数组排序. 程序SpaceRemover:显示输入字符串,并将其中所有的空格字符替换为句点字 ...
- Oracle EBS GL 会计科目报错 GL_ACCESS_SET_LEDGERS
1.会计科目设置后,总账中找不到对应账簿 2.原因是新版本系统物化视图有问题,参照metalink解决方案得知原路径 ...
- RHEL7系统管理常用工具
RHEL7提供大量系统管理工具,简要记录一下各工具的作用,后续再详细说明用法. 工具 描述 /proc linux的内存镜像目录./proc/sys目录下的文件能被临时修改,从而改变linux内核参数 ...