世界万事无简单一说, 每个事情基本上由多个小的事情来完成。有的事情会存在若小的事情不能同时完成的情况就取消所有的小的事情,直至都完成达到预期的效果才算完成!这样就用到了事务操作。在所有的sql语句完成之前,若发生异常,则让事务回滚到开始事务的时候,让事务结束;并且让已执行的sql语句作废。但是连接数据库的connnection与开启事务的connnection必须是一个。这样原来在dao层开启连接必须到service层一起执行了开启事务和处理异常。

一、事务:

一件事情有n个组成单元 :要不这n个组成单元同时成功, 要不n个单元就同时失败。就是将n个组成单元放到一个事务中!

二、mysql事务:

1、默认的事务:一条sql语句就是一个事务 。默认就开启事务并提交事务!

2、手动事务:

①、显示的开启一个事务:start transaction

此时进行的所有的修改都是内存里修改的,具体数据库内到底修改了没还是由是否提交来决定的!!!

当提交了就代表数据库修改了,当回滚了则没有修改!

但是需要注意的是无论数据库到底修改了没有,只要执行了SQL语句,在库内的表里的自增的序号会自动被占用了!!!

②、事务提交:commit

代表从开启事务到事务提交中间的所有的sql都认为有效! 真正的更新数据库!

③、事务的回滚:rollback

  代表事务的回滚--在其之前的所有的操作都作废了!回滚到start的地方,同时当前的事务结束了!

三、JDBC事务操作:

1、默认是自动事务:

执行sql语句:executeUpdate()  ---- 每执行一次executeUpdate方法 代表 事务自动提交(默认)<执行一句sql就是一个提交>

2、通过jdbc的API手动事务:

①、开启事务:conn.setAutoCommit(false);

此为设置为自动提交(改为false,也就是改为手动提交)

②、提交事务:conn.commit();

③、回滚事务:conn.rollback();          (都被封装成了方法)

注意:

控制事务的connnection必须是同一个!

执行sql的connection与开启事务的connnection必须是同一个才能对事务进行控制!!!

public static void main(String[] args) {
Connection conn = JDBCUtils.getConn();
Statement sta = null;
// Statement sta = conn.createStatement();
String sql = "insert into account(aname,money) values('wangwu',1000)";
// 手动开启事务
try {
sta = conn.createStatement();
conn.setAutoCommit(false);
sta.executeUpdate(sql);
} catch (SQLException e) {
// 回滚
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} finally {//注意好位置
try {
// 提交事务
conn.commit();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}

注:

Statement 对象用于将 SQL 语句发送到数据库中。实际上有三种 Statement 对象,它们都作为在给定连接上执行 SQL 语句的包容器:Statement、PreparedStatement(它从 Statement 继承而来)和 CallableStatement(它从 PreparedStatement 继承而来)。它们都专用于发送特定类型的 SQL 语句: Statement 对象用于执行不带参数的简单 SQL 语句;PreparedStatement 对象用于执行带或不带 IN 参数的预编译 SQL 语句;CallableStatement 对象用于执行对数据库已存储过程的调用

Statement 接口提供了执行语句和获取结果的基本方法。PreparedStatement 接口添加了处理 IN 参数的方法;而 CallableStatement 添加了处理 OUT 参数的方法。

四、DBUtils事务操作:

QueryRunner:

1、有参构造:QueryRunner runner = new QueryRunner(DataSource dataSource);

有参构造将数据源(连接池)作为参数传入QueryRunner,QueryRunner会从连 接池中获得一个数据库连接资源操作数据库,所以直接使用无Connection参数   的update方法即可操作数据库

2、无参构造:QueryRunner runner = new QueryRunner();-

无参的构造没有将数据源(连接池)作为参数传入QueryRunner,那么我们在使  用QueryRunner对象操作数据库时要使用有Connection参数的方法

<因为有参无法保证connection的唯一性,所以需要无参构造---并且需要手动获取连接>

public class MyDBUtils {
public static final String DRIVER = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8";
public static final String USERNAME = "root";
public static final String PASSWORD = "123456";
/*
* 创建连接池BasicDataSource
*/
public static BasicDataSource dataSource = new BasicDataSource();
//静态代码块(优先只执行一次)
static {
//对连接池对象 进行基本的配置
dataSource.setDriverClassName(DRIVER); // 这是要连接的数据库的驱动
dataSource.setUrl(URL); //指定要连接的数据库地址
dataSource.setUsername(USERNAME); //指定要连接数据的用户名
dataSource.setPassword(PASSWORD); //指定要连接数据的密码
}
/*
* 返回连接池对象
*/
public static DataSource getDataSource(){
return dataSource;
}
//返回一个连接对象
public static Connection getConn(){
Connection conn=null;
try {
conn= dataSource.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
}
    public static void main(String[] args) {
//获取连接池对象
QueryRunner qr = new QueryRunner();
//获取连接对象
Connection conn = MyDBUtils.getConn();
String sql = "update account set money = money - ? where aname = ?";
try {
//开启事务
conn.setAutoCommit(false);
qr.update(conn,sql,100,"zhangsan");
} catch (SQLException e) {
//回滚事务
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//提交事务
try {
conn.commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

五、转账实例:

public class AccountDao {
// 转出--需要和service层同一个conn 所以需要传值
public void Moneyout(
Connection conn,String out, double money) throws SQLException {
QueryRunner qr = new QueryRunner();
String sql = "update account set money = money - ? where aname = ?";
qr.update(conn, sql, money, out);
} // 转入
public void Moneyin(Connection conn,String in, double money) throws SQLException {
QueryRunner qr = new QueryRunner();
String sql = "update account set money = money + ? where aname = ?";
qr.update(conn, sql, money, in);
}
}
public class AccountService {
private AccountDao accountDao = new AccountDao();
// 转账--需要在此层处理事务,所以在此层获得CONN,再把这个参数传给dao层
public boolean transfer(String out, String in, double money) {
// 定义变量
boolean flag = true;
Connection conn = MyDBUtils.getConn();
try {
// 开启事务
conn.setAutoCommit(false);
accountDao.Moneyout(conn, out, money);
accountDao.Moneyin(conn, in, money);
} catch (SQLException e) {
flag = false;
// 如果出现异常,则flag返回一个false
// 回滚(当try出现异常后会执行catch,然后回滚到开启事务之前)
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace(); } finally {
// 提交
try {
conn.commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return flag;
}
}
public class TransferServlet extends HttpServlet {
private AccountService accountService =new AccountService();
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取页面上值
//解决中文乱码
request.setCharacterEncoding("UTF-8");
//获取转出账户
String out = request.getParameter("out");
//获取转入账户
String in = request.getParameter("in");
//获取转账金额(从前台获取的都是String类型)
String moneyStr = request.getParameter("money");
//将字符串金额转成double
double money = Double.parseDouble(moneyStr);
//调用 Service层的转账方法
boolean flag = accountService.transfer(out, in, money);
//解决response乱码
response.setContentType("text/html;charset=utf-8");
if(flag){
response.getWriter().write("转账成功");
}else{
response.getWriter().write("转账失败");
} } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

五、事务的特性和隔离级别:事务的特性ACID

    1、原子性(Atomicity)

    原子性是指事务是一个不可分割的工作单位,事务中的操作 要么都发生,要么都不发生。

     2、一致性(Consistency)

    一个事务中,事务前后数据的完整性必须保持一致。

     3、隔离性(Isolation)

    多个事务,事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。

     4、持久性(Durability)

    持久性是指一个事务一旦被提交,它对数据库中数据的改变 就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

JAVA基础之事务的更多相关文章

  1. [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html   谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...

  2. Java基础知识【上】(转载)

    http://blog.csdn.net/silentbalanceyh/article/details/4608272 (最终还是决定重新写一份Java基础相关的内容,原来因为在写这一个章节的时候没 ...

  3. Java基础常见英语词汇

    Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的                             ['prəʊɡræmɪŋ]编程 OO: object ...

  4. JAVA基础英语单词表(下)

    quantity                     / 'kwɔntiti /                    量,数量 query                             ...

  5. Java中的事务——JDBC事务和JTA事务

    Java中的事务——JDBC事务和JTA事务 转载:http://www.hollischuang.com/archives/1658 之前的事务介绍基本都是数据库层面的事务,本文来介绍一下J2EE中 ...

  6. Java 基础知识总结

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.数据类型:  数据类型:1>.基本数据类型:1).数值型: 1}.整型类型(byte  8位   (by ...

  7. 学习Spring必学的Java基础知识(1)----反射(转)

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...

  8. 学习Spring必学的Java基础知识(1)----反射

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...

  9. Java基础学习(1)——反射

    反射就是把Java类中的各种成分映射成相应的Java类(主要用于框架开发) 反射的基石–>Class类 Java程序中的各个类属于同一事物,描述这类事务的Java类名就是Class. Class ...

随机推荐

  1. OpenCV2 与opencv3 问题解决

    本文链接:https://blog.csdn.net/ling_xiobai/article/details/79691785今天使用opencv运行一个脚本,但是出现cv2.cv.BoxPoints ...

  2. 在 Alpine Linux 中安装 bash shell

    如何在我的 Alpine Linux LXD(Linux容器)虚拟机(VM)中安装 bash shell? Alpine Linux 自带 BusyBox 工具.它被评为“嵌入式 Linux 的瑞士军 ...

  3. Laya一个莫名其妙的报错laya.pathfinding

    版本2.2.0 莫名其妙,然后论坛查了下 把类库设置,不勾选这玩意就不报错了.

  4. 转 linux 添加PHP环境变量,/etc/profile 不生效,每次都要 source /etc/profile

    http://shanhuxueyuan.com/news/detail/46.html 执行php -v 提示未找到命令,这是因为没有将php路径添加到环境变量 方法一:直接运行命令export P ...

  5. Flask 学习(一)简单介绍

    Flask介绍(轻量级的框架) Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收ht ...

  6. vbscript--FileSystemObject详解

    https://blog.csdn.net/superbirds/article/details/6762748 FSO是FileSystemObject 或 Scripting.FileSystem ...

  7. light4j一个轻量级的低延时、高吞吐量、内存占用量小的API平台

    1.背景(abstract) 笔者算是一个极客类型的程序员了.喜欢探索一些程序内在的原理.稳定性.自动化运维.健壮性,很多时间也会 去对程序的内存使用率.cpu使用率锱铢必较.尽量克扣掉不必要的cpu ...

  8. EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器解决方案之Nodejs调用bat或sh脚本

    关于EasyDSS流媒体服务器 EasyDSS商用流媒体服务器解决方案是一套集流媒体点播.转码与管理.直播.录像.检索.时移回看于一体的一套完整的商用流媒体服务器解决方案,EasyDSS高性能RTMP ...

  9. ArcGIS Server 10.2忘记用户名密码的解决方案

    忘记了ArcGIS Server Manager的密码,可以采用以下方法进行重置. 1.找到ArcGIS Server的安装目录 D:\Program Files\ArcGIS\Server\tool ...

  10. Android Studio 开发

    Android studio安装与配置 (收藏) https://www.cnblogs.com/gufengchen/p/10991886.html ------------------------ ...