世界万事无简单一说, 每个事情基本上由多个小的事情来完成。有的事情会存在若小的事情不能同时完成的情况就取消所有的小的事情,直至都完成达到预期的效果才算完成!这样就用到了事务操作。在所有的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. An intriguing failing of convolutional neural networks and the CoordConv solution

    An intriguing failing of convolutional neural networks and the CoordConv solution NeurIPS 2018 2019- ...

  2. pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it's not in your path

    使用pytesseract识别验证码中遇到异常如下: pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installe ...

  3. WebGL学习笔记(十):雾化

    雾化是指距离我们较远的物体看不清晰的情况,比如模拟大雾环境,或者模拟水下环境时会用到. 实现雾化的方式有很多种,我们这里使用的是线性雾化的方式: 线性雾化 线性雾化比较简单,我们算出每个像素点到摄像机 ...

  4. GIT删除本地tag和远程tag

    以tag test为例,这个tag已经同步到远程,但是现在发现了一个问题,需要撤回该tag,git命令如下: 删除本地tag: git tag -d test 删除远程tag: git push or ...

  5. 报错:pymysql.err.InternalError: (1054, "Unknown column 'AType' in 'field list'")

    报错背景: 报错前sql代码展示: List = ['] # sql = "insert into test(id, name) value ("+"'"+ L ...

  6. Idea导入maven项目没有识别

    选中module的pom.xml,右键,选择" add as maven project",idea会识别该pom的项目  

  7. iOS - 判断程序每天只执行一次

    当进行操作的时候记录操作时间存在偏好设置当中,当再次点击的时候获取现在的时间然后和之前记录的时间进行比较.如果是一天那么就提示“今天已经操作过了”,如果不是一天,那么可以正常操作,然后记录操作时间.如 ...

  8. ejs不能读取js变量??????

    一.问题描述 用express搭了一个nodejs服务端,为了测试接口数据是否能够正常输出,用ejs作为模版引擎的html文件写js发请求. 1.请求正常,能在network看到,但是没有输出cons ...

  9. Docker应用容器化

    Docker 的核心思想就是如何将应用整合到容器中,并且能在容器中实际运行. 将应用整合到容器中并且运行起来的这个过程,称为“容器化”(Containerizing),有时也叫作“Docker化”(D ...

  10. spark sc.textFile() 指定换行符

    直接上代码 package com.jason.spark23 import org.apache.spark.sql.SparkSession import org.apache.spark.Spa ...