java 本地事务_java事务(二)——本地事务

news/2024/7/8 2:58:05

本地事务

事务类型

事务可以分为本地事务和分布式事务两种类型。这两种事务类型是根据访问并更新的数据资源的多少来进行区分的。本地事务是在单个数据源上进行数据的访问和更新,而分布式事务是跨越多个数据源来进行数据的访问和更新。在这里要说的事务是基于数据库这种数据源的。

JDBC事务

在JAVA中,我们使用JDBC来连接数据库,访问和更新数据。那么在JDBC中是如何实现事务的,事务是被谁来管理的?这个答案当然是数据库,JDBC本身并没有处理事务的能力,而是依赖于底层数据库,底层数据库来提供事务的服务。在很多资料上会提到,JDBC的事务是基于连接的,也就是那个Connection对象,这个连接的本质其实是连接到数据库的一个Socket,与数据库建立连接以后就可以向数据库发送指令和数据,最终数据库会根据接收到的指令和数据来进行增删改查以及事务的处理。另外,事务是被限制在单个连接上的,这就好像我们去银行的营业厅办理业务,营业厅有多个窗口,我们只会在自己的窗口上与银行工作人员进行沟通并处理自身的业务,而不能跨窗口,告诉别的窗口的工作人员把那哥们的钱转到自己卡上,这事也就只能想想。

数据库事务例子

下面先看一个MYSQL数据库事务的例子:

1、创建表

创建用户表

CREATE TABLEUSERS

(USER_ID INT NOT NULL AUTO_INCREMENT COMMENT '自增主键',USER_NAME VARCHAR(25) NOT NULL COMMENT '用户名',

PASSWORDVARCHAR(25) NOT NULL COMMENT '密码',

GENDERVARCHAR(1) COMMENT '性别',

PHONE_NOVARCHAR(11) NOT NULL COMMENT '手机号',

CREATE_TIMEDATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT '创建时间',PRIMARY KEY (USER_ID)

)

COMMENT= '用户表';

创建用户和角色的关联关系表

CREATE TABLEUSER_ROLE_RELATION

(

REL_IDINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',USER_ID INT NOT NULL COMMENT '用户ID',

ROLE_IDINT NOT NULL COMMENT '角色ID',PRIMARY KEY(REL_ID)

)

COMMENT= '用户和角色对应关系表'

2、创建存储过程,在存储过程中使用事务

BEGIN#声明一个标志位,默认为0DECLARE T_ERROR INTEGER DEFAULT 0;

#如果事务执行过程中出现异常,那么把标志位设置为1DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET T_ERROR = 1;

#开始事务

STARTTRANSACTION;INSERT INTO USERS (USER_NAME, PASSWORD, GENDER, PHONE_NO) VALUES ('zhangsan', '123456', '男', '11111111111');INSERT INTO USER_ROLE_RELATION (USER_ID, ROLE_ID) VALUES ('333', '1');

#如果执行成功,直接提交,否则回滚IF T_ERROR = 0 THEN

COMMIT;ELSE

ROLLBACK;END IF;END

3、执行存储过程

存储过程执行成功以后,数据库的这两个表中会分别出现一条记录。然后把

INSERT INTO USER_ROLE_RELATION (USER_ID, ROLE_ID) VALUES ('333', '1');

这个语句改为:

#这条INSERT语句违反了非空约束,会抛出异常INSERT INTO USER_ROLE_RELATION (USER_ID, ROLE_ID) VALUES (NULL, '1');

重新保存并执行存储过程,结果是两个表中都没有新增记录。两条SQL语句要么同时成功,要么同时失败。

JDBC事务例子

JDBC中如果需要手动提交事务的话,需要用到Connection对象中的三个方法:

//设置是否自动提交

setAutoCommit()//提交

commit()//回滚

rollback()

在JDBC中事务的提交方式默认是自动提交的,手动提交的事务的话需要更改默认设置:

Connection.setAutoCommit(false)

下面这个例子是假设新增一个用户并给用户赋默认权限,那么需要同时向两张表中分别插入一条记录,把新增用户和赋权限看做是一个执行单元,放在一个事务中。

packageperson.lb.jdbc;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;public classTestJDBCTransAction {static{try{//加载驱动类

Class.forName("com.mysql.jdbc.Driver");

}catch(ClassNotFoundException e) {

e.printStackTrace();

}

}public static voidmain(String[] args) {//执行事务

executeTransaction();

}private static voidexecuteTransaction() {

Connection conn= null;

Statement st1= null;

Statement st2= null;

ResultSet rs= null;try{//获取数据库连接

conn =(Connection) DriverManager.getConnection("jdbc:mysql://192.168.0.105:3306/TEST","root","root");

conn.setAutoCommit(false);

st1=(Statement) conn.createStatement();

st2=(Statement) conn.createStatement();//插入用户信息

st1.execute("INSERT INTO USERS (USER_NAME, PASSWORD, GENDER, PHONE_NO) "

+ "VALUES ('zhangsan', '123456', '男', '11111111111')", Statement.RETURN_GENERATED_KEYS);//获取增长列的新值

rs =st1.getGeneratedKeys();

String userID= "";if(rs.next()) {

userID= rs.getString(1);

}//插入用户和角色关联数据

st2.execute("INSERT INTO USER_ROLE_RELATION (USER_ID, ROLE_ID) VALUES (" +userID +", '1')");

conn.commit();

}catch(SQLException e) {

e.printStackTrace();try{

conn.rollback();

}catch(SQLException e1) {

e1.printStackTrace();

}

}finally{try{if(rs != null) {

rs.close();

}if(st1 != null) {

st1.close();

}if(st2 != null) {

st2.close();

}if(conn != null) {

conn.close();

}

}catch(SQLException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

程序执行结果如下:

USERS表

1affe0ce3f9b700fa9f0db18605abe5e.png

USER_ROLE_RELATION表

bcdf61a06dd10d4a1d9b7057b5e738be.png

到这里,JAVA的本地事务算是写完了。


http://www.niftyadmin.cn/n/3528578.html

相关文章

fitnesse java_从Fitnesse中学习Java单元测试

从第一次知道Fitnesse这个集成测试工具到现在也已经差不多有2年多的时间了。在这个期间把Fitnesse的源码也算是反反复复阅读了很多遍,算是对其实现的原理和方法有所了解。在最近一次对Fitnesse最新版本代码的研究中我发现,Fitnesse除了是一个很好的开源集…

java 获得basepath_JavaWeb项目获取绝对路径basePath

1. freemarker获取系统相对路径方式spring-mvc.xml 中配置其中是关键。ftl页面中设置首页js文件中获取pathvar base document.getElementById("base").href;// 与后台交互_send function(async, url, value, success, error) {$.ajax({async : async,url : base /…

java 分析工具_java分析工具

java分析工具jinfojstatjmapjstack1.jinfo查看java进程的扩展参数-flag 查看某个jvm参数-flag /- 动态开启或关闭部分jvm参数-flag namevalue 修改部分jvm参数flags 查看所有jvm参数-sysprops 查看系统参数(System.getProperties())①-flag 查看某个jvm参数jvm参数②flag /- 动…

Java web登录拦截器_SpringMVC拦截器实现登录认证

博客以Demo的形式讲诉拦截器的使用项目结构如图:需要的jar:有springMVC配置需要的jar和jstl需要的jarSpringMVC包的作用说明:aopalliance.jar:这个包是AOP联盟的API包,里面包含了针对面向切面的接口。通常spring等其它具备动态织入功能的框架…

java 文件备注_java文档注释:

java支持三种注释方式,前两种分别是//和/* */,第三种被称作说明注释,它以/**开始,以*/结束.说明注释允许你在程序中嵌入关于程序的信息,你可以使用javadoc工具软件来生成信息,并输出到html文件中。说明注释,使你更加方便的记录你的…

java 访问私有成员_javap反编译探寻内部类为何能访问外部私有成员

Java语言理论告诉我们内部类对象持有外部类对象的一个引用,这说明内部类与外部类还是独立的两个类,只不过内部类对象通过持有外部类的对象的引用来维持这个关系。通常任何一个类都不可能访问另一个类的私有成员,那么内部类是如何做到访问外部…

java dblink_Oracle中dblink的实际应用示例详解

前言本文介绍的是关于Oracle同义词dblink的实际应用,下面话不多说了,来一起看看详细的介绍吧。业务需求:原数据库(10.2.0.4.0),新数据库(11.2.0.3)由于程序的需求原因,现在需要把新库上的某个用户直接映射到老库用户下…

java数据库映射_java日期、时间以及数据库映射处理

继承关系:java.lang.Object->java.text.Format->java.text.DateForm->java.text.SimpleDateFormat日期代码:G年代,y年,M月,d日,h时(上下午1-12),H时(24小时制),m分钟&#…