ThreadLocal的介绍与运用( 三 )

?(4) 工具类 : JdbcUtils
package com.itheima.transfer.utils;import com.mchange.v2.c3p0.ComboPooledDataSource;import java.sql.Connection;import java.sql.SQLException;public class JdbcUtils {// c3p0 数据库连接池对象属性private static final ComboPooledDataSource ds = new ComboPooledDataSource();// 获取连接public static Connection getConnection() throws SQLException {return ds.getConnection();}//释放资源public static void release(AutoCloseable... ios){for (AutoCloseable io : ios) {if(io != null){try {io.close();} catch (Exception e) {e.printStackTrace();}}}}public static void commitAndClose(Connection conn) {try {if(conn != null){//提交事务conn.commit();//释放连接conn.close();}} catch (SQLException e) {e.printStackTrace();}}public static void rollbackAndClose(Connection conn) {try {if(conn != null){//回滚事务conn.rollback();//释放连接conn.close();}} catch (SQLException e) {e.printStackTrace();}}}? (5) dao层代码 : AccountDao
package com.itheima.transfer.dao;import com.itheima.transfer.utils.JdbcUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;public class AccountDao {public void out(String outUser, int money) throws SQLException {String sql = "update account set money = money - ? where name = ?";Connection conn = JdbcUtils.getConnection();PreparedStatement pstm = conn.prepareStatement(sql);pstm.setInt(1,money);pstm.setString(2,outUser);pstm.executeUpdate();JdbcUtils.release(pstm,conn);}public void in(String inUser, int money) throws SQLException {String sql = "update account set money = money + ? where name = ?";Connection conn = JdbcUtils.getConnection();PreparedStatement pstm = conn.prepareStatement(sql);pstm.setInt(1,money);pstm.setString(2,inUser);pstm.executeUpdate();JdbcUtils.release(pstm,conn);}}? (6) service层代码 : AccountService
package com.itheima.transfer.service;import com.itheima.transfer.dao.AccountDao;import java.sql.SQLException;public class AccountService {public boolean transfer(String outUser, String inUser, int money) {AccountDao ad = new AccountDao();try {// 转出ad.out(outUser, money);// 转入ad.in(inUser, money);} catch (Exception e) {e.printStackTrace();return false;}return true;}}? (7) web层代码 : AccountWeb
package com.itheima.transfer.web;import com.itheima.transfer.service.AccountService;public class AccountWeb {public static void main(String[] args) {// 模拟数据 : Jack 给 Rose 转账 100String outUser = "Jack";String inUser = "Rose";int money = 100;AccountService as = new AccountService();boolean result = as.transfer(outUser, inUser, money);if (result == false) {System.out.println("转账失败!");} else {System.out.println("转账成功!");}}}2.1.2 引入事务? 案例中的转账涉及两个DML操作: 一个转出 , 一个转入 。这些操作是需要具备原子性的 , 不可分割 。不然就有可能出现数据修改异常情况 。
public class AccountService {public boolean transfer(String outUser, String inUser, int money) {AccountDao ad = new AccountDao();try {// 转出ad.out(outUser, money);// 模拟转账过程中的异常int i = 1/0;// 转入ad.in(inUser, money);} catch (Exception e) {e.printStackTrace();return false;}return true;}}? 所以这里就需要操作事务 , 来保证转出和转入操作具备原子性 , 要么同时成功 , 要么同时失败 。
(1) JDBC中关于事务的操作的api
Connection接口的方法作用voidsetAutoCommit(false)禁用事务自动提交(改为手动)voidcommit();提交事务void rollback();回滚事务(2) 开启事务的注意点: