ThreadLocal:可以看作一個域,只是在這個類中存的資源數據,在同一個線程裏共享。而客戶端發送的一次請求都是同一個線程。
我們可以利用此類將一個Connection對象存入,而多個DAO用的是同一個Connection對象。因爲事務裏Connection必須是同一個。
例:轉帳
DbcpUtils.java
package cn.utils;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
public class DbcpUtils {
private static DataSource ds;
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
static {
try {
Properties prop = new Properties();
prop.load(DbcpUtils.class.getClassLoader().getResourceAsStream(
"dbcp.properties"));
ds = new BasicDataSourceFactory().createDataSource(prop);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static DataSource getDataSource() {
return ds;
}
public static Connection getConnection() {
Connection conn = tl.get();
if (conn == null) {
try {
conn = ds.getConnection();
tl.set(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
return conn;
}
public static void startTransaction() {
Connection conn = tl.get();
if (conn == null) {
conn = getConnection();
}
try {
conn.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void rollback() {
Connection conn = tl.get();
if (conn != null) {
try {
conn.rollback();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void commit() {
Connection conn = tl.get();
if (conn != null) {
try {
conn.commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void release() {
Connection conn = tl.get();
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
AccountDao.java
public class AccountDao {
private QueryRunner qr = new QueryRunner();
public void update(Account account) {
String sql = "update account set money=? where name=?";
Object[] param = { account.getMoney(), account.getName() };
try {
int num = qr.update(DbcpUtils.getConnection(), sql, param);
if(num>0){
System.out.println("轉帳成功");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public Account findAccountByName(String name) {
Connection conn = DbcpUtils.getConnection();
String sql = "select * from account where name=?";
Object[] params = { name };
try {
return qr.query(conn,sql, new BeanHandler<Account>(Account.class),
params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
AccountService.java
package cn.service;
import java.sql.Connection;
import java.sql.SQLException;
import cn.dao.AccountDao;
import cn.domain.Account;
import cn.utils.DbcpUtils;
public class AccountService {
AccountDao dao = new AccountDao();
public void transfer(String sourceName, String targetName, float money) {
// Connection conn = DbcpUtils.getConnection();
Account soAccount = dao.findAccountByName(sourceName);
Account taAccount = dao.findAccountByName(targetName);
soAccount.setMoney(soAccount.getMoney() - money);
taAccount.setMoney(taAccount.getMoney() + money);
DbcpUtils.startTransaction();
try {
dao.update(soAccount);
int i = 1 / 0;
dao.update(taAccount);
} catch (Exception e) {
DbcpUtils.rollback();
e.printStackTrace();
} finally{
DbcpUtils.commit();
}
}
}