java中的事务管理
2016-04-03 20:04
531 查看
package myweb.book.utils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbutils.DbUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class TransactionManager {
private TransactionManager() {
}
private static DataSource source = new ComboPooledDataSource();
private static ThreadLocal<Boolean> isTran_local = new ThreadLocal<Boolean>(){
@Override
protected Boolean initialValue() {//设置是否开启事务
return false;//--默认不开启事务控制
}
};
//--用它来存改造后的链接
private static ThreadLocal<Connection> proxyConn_local = new ThreadLocal<Connection>(){};
//--用它来存放真正的链接
private static ThreadLocal<Connection> realconn_local = new ThreadLocal<Connection>(){};
/**
* 开启事务控制
* @throws SQLException
*/
public static void startTran() throws SQLException{
isTran_local.set(true);//--将开启事务标记改为true
final Connection conn = source.getConnection();//获取链接对象
conn.setAutoCommit(false);//--将自动开启事务关闭
realconn_local.set(conn);//--Ϊ保存真正的链接对象
//-由于我想是一个链接可以用与多个对数据库操作,而每次操作后都会有隐式的关闭链接操作(close)所以用改造close
Connection proxyConn = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces()
, new InvocationHandler(){
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if("close".equals(method.getName())){//如果方法为close
return null;//将close操作不进行任何真正操作
}else{
return method.invoke(conn, args);//其他方法原样调用
}
}
});
proxyConn_local.set(proxyConn);//将改造的链接对象放存到对应的地方
}
/**
* 提交事务
*/
public static void commit(){
DbUtils.commitAndCloseQuietly(proxyConn_local.get());
}
/**
* 回滚事务
*/
public static void rollback(){
DbUtils.rollbackAndCloseQuietly(proxyConn_local.get());
}
/**
* 对于要开启事务的返回的链接都要是同一个,这就需要改造getConnection()的方法
* 对于不需开启事务就直接返回原连方法
* @return
* @throws SQLException
*/
public static DataSource getSource() throws SQLException{
if(isTran_local.get()){//--是否需要开启事务
return (DataSource) Proxy.newProxyInstance(source.getClass().getClassLoader(), source.getClass().getInterfaces()
,new InvocationHandler(){
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if("getConnection".equals(method.getName())){//如果方法是各同Connetion()则需要改造
return proxyConn_local.get();//返回存在本地线程池中的链接对象
}else{
return method.invoke(source, args);//其他方法直接返回
}
}
});
}else{//-对不需要开启事务的直接返回source
return source;
}
}
/**
* 释放资源
*/
public static void release(){
DbUtils.closeQuietly(realconn_local.get());//关闭链接֮
realconn_local.remove();
proxyConn_local.remove();
isTran_local.remove();
}
}
package myweb.book.factor;
import java.io.FileReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;
import myweb.book.annotion.Tran;
import myweb.book.dao.Dao;
import myweb.book.service.Service;
import myweb.book.utils.TransactionManager;
public class BasicFactory {
private static BasicFactory factory = new BasicFactory();
private static Properties prop = null;
private BasicFactory(){}
static{
try {
prop = new Properties();
prop.load(new FileReader(BasicFactory.class.getClassLoader().getResource("config.properties").getPath()));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static BasicFactory getFactory(){
return factory;
}
@SuppressWarnings("unchecked")
/**
* 生成service对象
*/
public <T extends Service> T getService(Class<T> clazz){
try{
//利用反射获取service对象
String infName = clazz.getSimpleName();
String implName = prop.getProperty(infName);
final T service = (T) Class.forName(implName).newInstance();
//动态改造service对象使其可以实现对事务的控制
T proxyService = (T) Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces()
, new InvocationHandler(){
//改造service对象中的方法
public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {
if(method.isAnnotationPresent(Tran.class)){//判断service对象中的方法是否需要开启事务控制(是)
try{
TransactionManager.startTran();//开启一个事务
Object obj = method.invoke(service, args);//调用原有方法
TransactionManager.commit();//提交事务
return obj;
}catch (InvocationTargetException e) {
TransactionManager.rollback();//--回滚事务
throw new RuntimeException(e.getTargetException());
} catch (Exception e) {
TransactionManager.rollback();//--回滚事务
throw new RuntimeException(e);
}finally{
TransactionManager.release();//--释放资源
}
}else{//不需要开启事务直接返回原方法
return method.invoke(service, args);
}
}
});
return proxyService;
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 生成dao对象
*/
public <T extends Dao> T getDao(Class<T> clazz){
try{
String infName = clazz.getSimpleName();
String implName = prop.getProperty(infName);
return (T) Class.forName(implName).newInstance();
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbutils.DbUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class TransactionManager {
private TransactionManager() {
}
private static DataSource source = new ComboPooledDataSource();
private static ThreadLocal<Boolean> isTran_local = new ThreadLocal<Boolean>(){
@Override
protected Boolean initialValue() {//设置是否开启事务
return false;//--默认不开启事务控制
}
};
//--用它来存改造后的链接
private static ThreadLocal<Connection> proxyConn_local = new ThreadLocal<Connection>(){};
//--用它来存放真正的链接
private static ThreadLocal<Connection> realconn_local = new ThreadLocal<Connection>(){};
/**
* 开启事务控制
* @throws SQLException
*/
public static void startTran() throws SQLException{
isTran_local.set(true);//--将开启事务标记改为true
final Connection conn = source.getConnection();//获取链接对象
conn.setAutoCommit(false);//--将自动开启事务关闭
realconn_local.set(conn);//--Ϊ保存真正的链接对象
//-由于我想是一个链接可以用与多个对数据库操作,而每次操作后都会有隐式的关闭链接操作(close)所以用改造close
Connection proxyConn = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces()
, new InvocationHandler(){
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if("close".equals(method.getName())){//如果方法为close
return null;//将close操作不进行任何真正操作
}else{
return method.invoke(conn, args);//其他方法原样调用
}
}
});
proxyConn_local.set(proxyConn);//将改造的链接对象放存到对应的地方
}
/**
* 提交事务
*/
public static void commit(){
DbUtils.commitAndCloseQuietly(proxyConn_local.get());
}
/**
* 回滚事务
*/
public static void rollback(){
DbUtils.rollbackAndCloseQuietly(proxyConn_local.get());
}
/**
* 对于要开启事务的返回的链接都要是同一个,这就需要改造getConnection()的方法
* 对于不需开启事务就直接返回原连方法
* @return
* @throws SQLException
*/
public static DataSource getSource() throws SQLException{
if(isTran_local.get()){//--是否需要开启事务
return (DataSource) Proxy.newProxyInstance(source.getClass().getClassLoader(), source.getClass().getInterfaces()
,new InvocationHandler(){
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if("getConnection".equals(method.getName())){//如果方法是各同Connetion()则需要改造
return proxyConn_local.get();//返回存在本地线程池中的链接对象
}else{
return method.invoke(source, args);//其他方法直接返回
}
}
});
}else{//-对不需要开启事务的直接返回source
return source;
}
}
/**
* 释放资源
*/
public static void release(){
DbUtils.closeQuietly(realconn_local.get());//关闭链接֮
realconn_local.remove();
proxyConn_local.remove();
isTran_local.remove();
}
}
package myweb.book.factor;
import java.io.FileReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;
import myweb.book.annotion.Tran;
import myweb.book.dao.Dao;
import myweb.book.service.Service;
import myweb.book.utils.TransactionManager;
public class BasicFactory {
private static BasicFactory factory = new BasicFactory();
private static Properties prop = null;
private BasicFactory(){}
static{
try {
prop = new Properties();
prop.load(new FileReader(BasicFactory.class.getClassLoader().getResource("config.properties").getPath()));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static BasicFactory getFactory(){
return factory;
}
@SuppressWarnings("unchecked")
/**
* 生成service对象
*/
public <T extends Service> T getService(Class<T> clazz){
try{
//利用反射获取service对象
String infName = clazz.getSimpleName();
String implName = prop.getProperty(infName);
final T service = (T) Class.forName(implName).newInstance();
//动态改造service对象使其可以实现对事务的控制
T proxyService = (T) Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces()
, new InvocationHandler(){
//改造service对象中的方法
public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {
if(method.isAnnotationPresent(Tran.class)){//判断service对象中的方法是否需要开启事务控制(是)
try{
TransactionManager.startTran();//开启一个事务
Object obj = method.invoke(service, args);//调用原有方法
TransactionManager.commit();//提交事务
return obj;
}catch (InvocationTargetException e) {
TransactionManager.rollback();//--回滚事务
throw new RuntimeException(e.getTargetException());
} catch (Exception e) {
TransactionManager.rollback();//--回滚事务
throw new RuntimeException(e);
}finally{
TransactionManager.release();//--释放资源
}
}else{//不需要开启事务直接返回原方法
return method.invoke(service, args);
}
}
});
return proxyService;
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 生成dao对象
*/
public <T extends Dao> T getDao(Class<T> clazz){
try{
String infName = clazz.getSimpleName();
String implName = prop.getProperty(infName);
return (T) Class.forName(implName).newInstance();
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
相关文章推荐
- 20145335郝昊《java程序设计》第5周学习总结
- Ubuntu 16.04配置JDK1.8.0_77教程
- 20145303 《Java程序设计》第5周学习总结
- JAVAEE学习查询
- java 工厂模式
- 【java集合框架源码剖析系列】java源码剖析之LinkedList
- 【java集合框架源码剖析系列】java源码剖析之LinkedList
- 模拟spring中的IOC容器
- Java EE (14) -- SSH配置
- Java 大数之卡特兰数 HDU1130统计二叉树的数量
- Java多线程之synchronized及死锁编写
- 解决Spring MVC中文乱码
- Spring整合MyBatis
- Java 按值传递
- RxJava-变换操作
- javaweb-国际化
- 用ECLIPSE编译RPI QEMU的kernel
- struts2笔记01-环境搭建
- 资源清理
- Java 四种线程池的用法分析