新建Dbutils
//MyDBCPUtils public class MyDBCPUtils { private static DataSource ds; public static DataSource getDs() { return ds; } static { try { InputStream in = MyDBCPUtils.class.getClassLoader() .getResourceAsStream("dbcpconfig.properties"); Properties prop = new Properties(); prop.load(in); // 框架提供的数据源 BasicDataSourceFactory factory = new BasicDataSourceFactory(); ds = factory.createDataSource(prop); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } //建立连接 public static Connection getConnection() throws SQLException { return ds.getConnection(); // 返回一个被包装过的connection,所以用户可以直接关掉。关掉其实就是放回连接池了。 } //释放资源 public static void releaseResource(Statement st, ResultSet rs, Connection conn) { if (st != null) { try { st.close(); } catch (SQLException e) { e.printStackTrace(); } } if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }配置文件放在src下
#连接设置 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mytest username=root password=123456 #<!-- 初始化连接 --> initialSize=10 #最大连接数量 maxActive=50 #<!-- 最大空闲连接 --> maxIdle=20 #<!-- 最小空闲连接 --> minIdle=5 #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 --> maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] #注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。 connectionProperties=useUnicode=true;characterEncoding=utf8 #指定由连接池所创建的连接的自动提交(auto-commit)状态。 defaultAutoCommit=true #driver default 指定由连接池所创建的连接的只读(read-only)状态。 #如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix) defaultReadOnly= #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。 #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=REPEATABLE_READ新建JavaBean
package com.cskaoyan.bean; public class Account { private String username; private int money; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } public Account(String username, int money) { super(); this.username = username; this.money = money; } public Account() { super(); // TODO Auto-generated constructor stub } @Override public String toString() { return "Account [username=" + username + ", money=" + money + "]"; } }UserDao和UserService来处理转账业务
//UserService import com.cskaoyan.bean.Account; import com.cskaoyan.dao.TransactionUtils; import com.cskaoyan.dao.UserDao; import com.cskaoyan.dao.UserDaoImpl; import com.cskaoyan.db.MyDBCPUtils; public class UserService { // 转账是一个事务,要么全部成功,要么全部不成功 public void transferMoney(String usernameFrom, String usernameTo, int money) { UserDao dao = new UserDaoImpl(); dao.transfer(usernameFrom, usernameTo, money); } // 把转账的业务逻辑放回到service层 public void transferMoney2(String usernameFrom, String usernameTo, int money) { UserDao dao = new UserDaoImpl(); Connection connection = null; try { //开启事务 TransactionUtils.startTransaction(); // 需要先查询下多少钱,然后再转 Account accout_from = dao.getAccout(usernameFrom);// 汇款人 Account accout_to = dao.getAccout(usernameTo);// 收款人 // 业务计算 accout_from.setMoney(accout_from.getMoney() - money); // 把usernameFrom 更新成新的accout_from dao.updateAccout(accout_from); int i = 1 / 0;// 此处应当有计算 accout_to.setMoney(accout_to.getMoney() + money); dao.updateAccout(accout_to);// 把usernameTo更新成新的accout_to //提交事务 TransactionUtils.commitTransaction(); } catch (Exception e) { e.printStackTrace(); //回滚事务 TransactionUtils.rollbackTransaction(); } } }JunitTest
@Test public void testTrans() { UserService service=new UserService(); service.transferMoney("e", "f", 100); }