在分别讨论这两种方法之前,我们需要先讨论一下在处理数据库的时候的异常的处理。我这里做了一个TransactionException继承至RuntimeException然后在拦截器里面抛出,再又应用框架处理这个异常。下面试这个类的代码:
public class TransactionException extends RuntimeException { private Throwable superException; private String myMessage; public TransactionException(Throwable throwable){ super(throwable); this.superException = throwable; } public TransactionException(Throwable throwable,String message){ super(message,throwable); this.superException = throwable; this.myMessage = message; } /** * @return Returns the myMessage. */ public String getMessage() { return myMessage; } /** * @return Returns the superException. */ public Throwable getSuperException() { return superException; } /** * @param myMessage The myMessage to set. */ public void setMyMessage(String message) { this.myMessage = message; } /** * @param superException The superException to set. */ public void setSuperException(Throwable superException) { this.superException = superException; } }
1) 通过方法的第一个参数传进去
l DAO
import java.sql.Connection; public class TestDao { public void insertA(Connection con,String a,String b,……){ ………………………………………… 一系列操作 ………………………………………… } public String queryA(Connection con,…….){ ………………………………………… 一系列操作 ………………………………………… } public void updateA(Connection con,…….){ ………………………………………… 一系列操作 ………………………………………… } }
l 拦截器
import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class TransactionInterceptor implements Interceptor { public void before(InvokeJniInfo invInfo) { if(isNeedTransactions(invInfo)){ Connection conn = (Connection) invInfo.getArgs()[0]; try { conn.setAutoCommit(false); } catch (SQLException e) { throw new TransactionException(e); } } } public void after(InvokeJniInfo invInfo) { if(isNeedTransactions(invInfo)){ Connection conn = (Connection) invInfo.getArgs()[0]; try { conn.commit(); } catch (SQLException e) { throw new TransactionException(e); }finally{ if(conn != null){ try { conn.close(); } catch (SQLException e) { throw new TransactionException(e,"Close Connection is failure!"); } } } } } public void exceptionThrow(InvokeJniInfo invInfo) { if(isNeedTransactions(invInfo)){ Connection conn = (Connection) invInfo.getArgs()[0]; try { conn.rollback(); } catch (SQLException e) { throw new TransactionException(e); }finally{ if(conn != null){ try { conn.close(); } catch (SQLException e) { throw new TransactionException(e,"Close Connection is failure!"); } } } } } private List getNeedTransaction(){ List needTransactions = new ArrayList(); needTransactions.add("insert"); needTransactions.add("update"); return needTransactions; } private boolean isNeedTransactions(InvokeJniInfo invInfo){ String needTransaction = ""; List needTransactions = getNeedTransaction(); for(int i = 0;i needTransaction = (String)needTransactions.get(i); if(invInfo.getMethod().getName().startsWith(needTransaction)){ return true; } } return false; } }
需要注意的是:getNeedTransaction就是需要进行事务处理的方法的开头,这个方法可以写成一个从配置文件里面去读,这里我就写死在里面了。只是对insert和update开头的方法进行事务控制。
2) 将Connection对象放在ThreadLocal中
l ConnectionUtil类:
import java.sql.Connection; public final class ConnectionUtil { private static ThreadLocal connections = new ThreadLocal(); public static Connection getConnection(){ Connection conn = null; conn = (Connection) connections.get(); if(conn == null){ conn = getRealConnection(); connections.set(conn); } return conn; } public static void realseConnection(Connection conn){ connections.set(null); } private static Connection getRealConnection() { 实现自己获取连接的代码 return null; } }
l DAO类
public class TestDao { public void insertA(String a,String b){ Connection conn = getConnection(); ………………………………………… 一系列操作 ………………………………………… } public String queryA(Connection con,…….){ Connection conn = getConnection(); ………………………………………… 一系列操作 ………………………………………… } public void updateA(Connection con,…….){ Connection conn = getConnection(); ………………………………………… 一系列操作 ………………………………………… } private Connection getConnection(){ return ConnectionUtil.getConnection(); } }
l 拦截器
import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class TransactionInterceptor implements Interceptor { public void before(InvokeJniInfo invInfo) { if(isNeedTransactions(invInfo)){ Connection conn = getConnection(); try { conn.setAutoCommit(false); } catch (SQLException e) { throw new TransactionException(e); } } } public void after(InvokeJniInfo invInfo) { if(isNeedTransactions(invInfo)){ Connection conn = getConnection(); try { conn.commit(); } catch (SQLException e) { throw new TransactionException(e); }finally{ if(conn != null){ try { conn.close(); releaseConnection(conn); } catch (SQLException e) { throw new TransactionException(e,"Close Connection is failure!"); } } } } } public void exceptionThrow(InvokeJniInfo invInfo) { if(isNeedTransactions(invInfo)){ Connection conn = getConnection(); try { conn.rollback(); } catch (SQLException e) { throw new TransactionException(e); }finally{ if(conn != null){ try { conn.close(); releaseConnection(conn); } catch (SQLException e) { throw new TransactionException(e,"Close Connection is failure!"); } } } } } private Connection getConnection(){ return ConnectionUtil.getConnection(); } private void releaseConnection(Connection conn){ ConnectionUtil.releaseConnection(conn); } private List getNeedTransaction(){ List needTransactions = new ArrayList(); needTransactions.add("insert"); needTransactions.add("update"); return needTransactions; } private boolean isNeedTransactions(InvokeJniInfo invInfo){ String needTransaction = ""; List needTransactions = getNeedTransaction(); for(int i = 0;i needTransaction = (String)needTransactions.get(i); if(invInfo.getMethod().getName().startsWith(needTransaction)){ return true; } } return false; } }
最后将这个拦截器添加到AOP拦截框架中去,InterceptorHandler类中的getIntercetors方法中添加一个:
private synchronized List getIntercetors(){ if(null == interceptors){ interceptors = new ArrayList(); …………………………………… interceptors.add(new TransactionInterceptor ()); …………………………………… } return interceptors; }
到此全部ok!