世界万事无简单一说, 每个事情基本上由多个小的事情来完成。有的事情会存在若小的事情不能同时完成的情况就取消所有的小的事情,直至都完成达到预期的效果才算完成!这样就用到了事务操作。在所有的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. 【Python】解析Python中的装饰器

    python中的函数也是对象,函数可以被当作变量传递. 装饰器在python中功能非常强大,装饰器允许对原有函数行为进行扩展,而不用硬编码的方式,它提供了一种面向切面的访问方式. 装饰器 一个普通的装 ...

  2. 使用NPOI或EPPlus来导出Excel文件实例,可在Excel文件加密

    使用NPOI.dll组件来导出Excel文件,并设置样式,Nuget引用即可. packages\NPOI.2.1.3.1\lib\net20\NPOI.dll #region Excel prote ...

  3. @JsonInclude(Include.NON_NULL) resttemplate 传递实体参数时 序列化为json时 空字符串不参与序列化

    @JsonInclude(Include.NON_NULL) resttemplate 传递实体参数时 序列化为json时 空字符串不参与序列化 https://www.cnblogs.com/sup ...

  4. Error-ASP.NET:未能加载文件或程序集“CMSCalendar”或它的某一个依赖项。系统找不到指定的文件。

    ylbtech-Error-ASP.NET:未能加载文件或程序集“CMSCalendar”或它的某一个依赖项.系统找不到指定的文件. 1.返回顶部 1. “/”应用程序中的服务器错误. 分析器错误 说 ...

  5. vue 动态路由跳转在新窗口打开

    let routeUrl =this.$router.resolve({path: '/home'}) window.open(routeUrl.href, '_blank');

  6. 【GMT43智能液晶模块】例程十八:LAN_HTTP实验——网页服务器

    源代码下载链接: 链接:https://pan.baidu.com/s/1sr4a7TBPyvs18jTfCfVj8Q 提取码:jwfv 复制这段内容后打开百度网盘手机App,操作更方便哦 GMT43 ...

  7. Java 学习大纲

    1.java基础 1.1 Collection和Map     (1)掌握Collection和Map的继承体系     (2)掌握ArrayList,LinkedList,Vector,Stack, ...

  8. 解决support包引起的AndroidStudio编译报错

    {"kind":"error","text":"error: resource android:attr/colorError n ...

  9. springboot 读取配置文件

    读取配置文件 在以前的项目中我们主要在 XML 文件中进行框架配置,业务的相关配置会放在属性文件中,然后通过一个属性读取的工具类来读取配置信息. 在 Spring Boot 中我们不再需要使用这种方式 ...

  10. EasyNVR网页摄像机无插件H5、谷歌Chrome直播方案之使用RTSP流判断摄像机设备是否在线以及快照抓取

    背景分析 熟知EasyNVR产品的小伙伴都知道,通过纯Web化的交互方式,只要配置出摄像机的IP.端口.用户名.密码等信息,就可以将地址进行通道配置完成,即可将设备接入.如果设备支持Onvif协议,E ...