事务操作
- 事务: 指的是逻辑上的⼀组操作,组成这组操作的各个单元要么全都成功,要么全都失败.
- 事务作⽤:保证在⼀个事务中多次SQL操作要么全都成功,要么全都失败.
mysql事务操作
sql语句 | 描述 |
start transaction | 开启事务 |
commit | 提交事务 |
rollback | 回滚事务 |
准备数据
# 创建账号表
create table account(
id int primary key auto_increment,
name varchar(20),
money double
);
# 初始化数据
insert into account values (null,'jack',10000);
insert into account values (null,'rose',10000);
insert into account values (null,'tom',10000);
操作
MYSQL中可以有两种⽅式进⾏事务的管理:
- ⾃动提交:MySql默认⾃动提交。即执⾏⼀条sql语句提交⼀次事务。
- ⼿动提交:先开启,再提交
⼿动提交
start transaction;
update account set money=money-1000 where name='jack';
update account set money=money+1000 where name='rose';
commit; #或者
rollback;
jdbc事务操作
Connection
对象的⽅法名
|
描述
|
conn.setAutoCommit(false)
|
开启事务
|
conn.commit()
|
提交事务
|
conn.rollback()
|
回滚事务
|
/*JDBC 的事务操作 */
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TransactionDemo {
/*
1.获得连接
2.开始事务
3. 具体的sql操作(加钱, 减钱)
4. 提交事务
5.如果出现异常, 回滚事务
6.释放资源
*/
@Test
public void test1() throws SQLException {
Connection conn = null;
try{
//1,获取连接
conn = DruidUtils.getConnection();
//2,开启事务
conn.setAutoCommit(false);
//3.具体的sql操作(加钱,减钱)
//减钱
String sql="update account set money=money-? where name = ?";
PreparedStatement pstat= conn.prepareStatement(sql);
pstat.setDouble(1,1000);
pstat.setString(2,"jack");
pstat.executeUpdate();
//模拟错误
//int n = 1/0;
//加钱
//sql是String引用变量
sql = "update account set money = money+? where name = ?";
//pstat 不能重复利用,每个sql一个预编译对象
PreparedStatement pstat2 = conn.prepareStatement(sql);
pstat2.setDouble(1,1000);
pstat2.setString(2,"rose");
pstat2.executeUpdate();
//提交事务
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
//如果出现异常,回滚事务
conn.rollback();
}
}
}
DbUtiles事务
Connection
对象的⽅法名
|
描述
|
conn.setAutoCommit(false)
|
开启事务
|
new QueryRunner()
|
创建核⼼类,不设置数据源
(
⼿动管理连接)
|
query(conn , sql , handler, params )
或
update(conn, sql , params)
|
⼿动传递连接, 执⾏
SQL
语句
CRUD
|
DbUtils.commitAndCloseQuietly(conn)
|
提交并关闭连接,不抛异常
|
DbUtils.rollbackAndCloseQuietly(conn)
|
回滚并关闭连接,不抛异常
|
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
/*
DBUtils 的事务操作
*/
public class TransactionDemo2 {
/*
1.获得连接
2.开始事务
3.具体的sql操作(加钱, 减钱)
4.提交事务 ,释放资源
5.如果出现异常, 回滚事务释放资源
*/
@Test
public void test(){
Connection conn = null;
try{
//1.获取连接
conn=DruidUtils.getConnection();
//2.开启事务
conn.setAutoCommit(false);
//3.具体的sql操作(加钱,减钱)
QueryRunner qr = new QueryRunner();
//减钱
String sql = "update account set money=money-? where name =?";
qr.update(conn,sql,1000,"jack");
//模拟错误
//int n = 1/0;
//加钱
sql="update account set money = money+? where name = ?";
qr.update(conn,sql,1000,"rose");
//4.提交事务,释放资源
DbUtils.commitAndCloseQuietly(conn);
} catch (SQLException e) {
e.printStackTrace();
//如果出现异常,回滚事务释放资源
DbUtils.commitAndCloseQuietly(conn);
}
}
}
JavaEE分层开发思想
分层开发思想
- 开发中,常使⽤分层思想
- 不同的层次结构分配不同的解决过程,各个层次间组成严密的封闭系统
- 分层的⽬的是:
- 解耦
- 可维护性
- 可重⽤性
- 不同层次,使⽤不同的包表示
- com.wensong 公司域名倒写
- com.wensong.dao dao层
- com.wensong.service service层
- com.wensong.pojo javabean
- com.wensong.utils ⼯具
案例:使⽤分层开发思想, 完成转账
代码实现
步骤
1
:编写⼊⼝程序
import java.sql.SQLException;
/**
* 程序执⾏的⼊⼝
*/
public class TestAccount {
/*
1. 模拟数据 扣款⼈ 收款⼈ ⾦额
2. 调⽤AccountService中 转账⽅法
3. 打印 转账后的结果 ( 成功, 失败)
*/
public static void main(String[] args){
//1.,模拟数据扣款人 收款人 金额
String outUser = "jack";//扣款人
String inUser = "rose";//收款人
Double money = 1000.0;//金额
//2.调用AccountService中的 转账 方法
AccountService service = new AccountService();
try{
service.transfer(outUser,inUser,money);
System.out.println("转账成功!");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("转账失败!");
}
}
}
service层
import java.sql.Connection;
import java.sql.SQLException;
public class AccountService {
/**
* 转账⽅法
* 参数1 : 扣款⼈
* 参数2 : 收款⼈
* 参数3 : ⾦额
*/
public void transfer(String outUser, String inUser, Double money) throws SQLException {
/*
事务控制, 保证 转账的操作 结果的⼀致性
1. 获取Connection对象
2. ⼿动开启事务
3. 执⾏ 减钱 加钱操作
4. 提交事务
5. 如果出现异常, 回滚事务
*/
Connection conn = null;
try{
//1.获取连接对象
conn = DruidUtils.getConnection();
//2.手动开启事务
conn.setAutoCommit(false);
//3.执行减钱 加钱 操作
//调用dao层方法 完成 减钱 加钱造作
AccountDao dao = new AccountDao();
//减钱
dao.out(conn,outUser,money);
//模拟错误
//int n = 1/0;
//加钱操作
dao.in(conn,inUser,money);
//4,提交事务
conn.commit();
}catch (Exception e){
e.printStackTrace();
//5.如果出现异常,回滚事务
conn.rollback();
}
}
}
dao层
import org.apache.commons.dbutils.QueryRunner;
import java.sql.Connection;
import java.sql.SQLException;
public class AccountDao {
/**
* 扣钱⽅法
* @param outUser 扣钱⼈
* @param money ⾦额
*/
public void out(Connection conn, String outUser ,Double money) throws SQLException {
String sql = "update account set money=money-? where name = ?";
QueryRunner qr = new QueryRunner();
qr.update(conn,sql,1000,"jack");
}
/**
* 加钱⽅法
* @param inUser 收钱⼈
* @param money ⾦额
*/
public void in(Connection conn,String inUser,Double money) throws SQLException {
String sql = "update account set money =money+? where name=?";
QueryRunner qr = new QueryRunner();
qr.update(conn,sql,1000,"rose");
}
}