DAO跨事務調用(ThreadLocal)

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();
		}

	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章