JAVA基础之事务
世界万事无简单一说, 每个事情基本上由多个小的事情来完成。有的事情会存在若小的事情不能同时完成的情况就取消所有的小的事情,直至都完成达到预期的效果才算完成!这样就用到了事务操作。在所有的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 接口提供了执行语句和获取结果的基本方法。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基础之事务的更多相关文章
- [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)
如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html 谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...
- Java基础知识【上】(转载)
http://blog.csdn.net/silentbalanceyh/article/details/4608272 (最终还是决定重新写一份Java基础相关的内容,原来因为在写这一个章节的时候没 ...
- Java基础常见英语词汇
Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的 ['prəʊɡræmɪŋ]编程 OO: object ...
- JAVA基础英语单词表(下)
quantity / 'kwɔntiti / 量,数量 query ...
- Java中的事务——JDBC事务和JTA事务
Java中的事务——JDBC事务和JTA事务 转载:http://www.hollischuang.com/archives/1658 之前的事务介绍基本都是数据库层面的事务,本文来介绍一下J2EE中 ...
- Java 基础知识总结
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.数据类型: 数据类型:1>.基本数据类型:1).数值型: 1}.整型类型(byte 8位 (by ...
- 学习Spring必学的Java基础知识(1)----反射(转)
引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...
- 学习Spring必学的Java基础知识(1)----反射
引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...
- Java基础学习(1)——反射
反射就是把Java类中的各种成分映射成相应的Java类(主要用于框架开发) 反射的基石–>Class类 Java程序中的各个类属于同一事物,描述这类事务的Java类名就是Class. Class ...
随机推荐
- linux 实时监控网速脚本(转)
#!/bin/bash ethn=$ while true do RX_pre=$(cat /proc/net/dev | grep $ethn | sed 's/:/ /g' | awk '{pri ...
- Hash算法及java HashMap底层实现原理理解(含jdk 1.7以及jdk 1.8)
现在很多公司面试都喜欢问java的HashMap原理,特在此整理相关原理及实现,主要还是因为很多开发集合框架都不甚理解,更不要说各种其他数据结构了,所以造成面子造飞机,进去拧螺丝. 1.哈希表结构的优 ...
- 【GMT43智能液晶模块】例程二十二:USB_CDC实验——高速数据传输
源代码下载链接: 链接:https://pan.baidu.com/s/10KOWONWbNYlonyuX0W0Mcg 提取码:ggpo 复制这段内容后打开百度网盘手机App,操作更方便哦 GMT43 ...
- 利用c# 多屏显示
公司搞了一个电视墙,要显示不同内容,于是买了一个多接口显卡(现在看来这个方案不是太好,但非常省钱) 要打开的就是几个网页,但要自己手工拖到不同电视上,非常麻烦 于是查了一下资料,发现可以用代码实现,说 ...
- mysql查看连接情况
1.使用navicat进入命令行或者命令行进入mysql 2.看所有进程 show full processlist; 3.看所有连接show status like 'Threads%';
- 关于在windows平台下将应用制作成windows服务及服务依赖的感想
在某些情况下,应用需要部署在windows平台下,单纯的手动点击exe执行文件或java -jar xxx.jar在实际生产环境中不是最佳实践(制作成bat启动文件置于启动项里,服务器启动后,需要人工 ...
- bootCDN引用的bootstrap前端框架套件和示例
这是bootCDN上引用的bootstrap前端框架套件,由多个框架组合而成,方便平时学习和测试使用.生产环境要仔细琢磨一下,不要用开发版,而要用生产版.bootCDN的地址是:https://www ...
- C#.NET XML 与 实体 MODEL 互转,非序列化
只能处理简单结构XML 和 实体. using System.Text; using System.Xml; namespace A.Util { public static class MyXmlU ...
- Windows Server 2008 R2怎样设置自动登陆(登录)
方法一: 打开电脑“菜单”,右键点击“运行”,在对话框输入“control userpasswords2”,点击“确定”. 弹出的窗口取消勾选“要使用本机用户必须输入用户名和密码”,取消后点击“确定” ...
- jquery关于on click事件的理解
jquery关于on click事件的理解 <pre><a style="min-width:60px; margin-left:6px;" wenzhangid ...