数据库JDBC(事务操作&ThreadLocal)1

事务操作

  • 事务: 指的是逻辑上的⼀组操作,组成这组操作的各个单元要么全都成功,要么全都失败.
  • 事务作⽤:保证在⼀个事务中多次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");
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40959890/article/details/107749459