浏览 5888 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-02-23
目前有一个系统,系统已经写好了,但是要不停的添加新的功能,用Struts, 业务逻辑写在Action中,以后可能增加一层Service。 业务处理和持久层没有使用任何框架,目前是用Dao担任业务处理加持久层双重操作, 但是有些业务处理很复杂,固设计了一个事务处理框架,大家帮我看下有没有线程安全的问题, 第一次使用ThreadLocal,请多指教。 Connection Holder 代码 public class ConnectionHolder { private Connection connection = null; private boolean rollback = false; private boolean isreadonly = false; public boolean isIsreadonly() { return isreadonly; } public void setIsreadonly(boolean isreadonly) { this.isreadonly = isreadonly; } public Connection getConnection() { if (null == connection) throw new RuntimeException("connection not exist........"); return connection; } public void setConnection(Connection connection) { this.connection = connection; } public boolean isRollback() { return rollback; } public void setRollback(boolean rollback) { this.rollback = rollback; } } TransactionManager 代码 public class TransactionManager { private static final Log logger = LogFactory .getLog(TransactionManager.class); private static ThreadLocal _thread = new ThreadLocal(); private static void safeCloseConnection(Connection con) { try { if (null != con) con.close(); con = null; } catch (Exception e) { logger.error("", e); } } public static void begin() { begin(false); } public static void begin(boolean isReadonly) { ConnectionHolder holder = null; Connection con = null; try { con = JNDIUtils.getConnection(); if (!isReadonly) { con.setAutoCommit(false); } holder = new ConnectionHolder(); holder.setConnection(con); holder.setIsreadonly(isReadonly); _thread.set(holder); } catch (Exception e) { safeCloseConnection(con); logger.error("", e); throw new RuntimeException(); } } private static void commit() { ConnectionHolder holder = null; Connection con = null; try { holder = getConnectionHolder(); con = holder.getConnection(); if (!holder.isRollback() && !holder.isIsreadonly()) { con.commit(); con.setAutoCommit(true); } } catch (Exception e) { logger.error("", e); } finally { safeCloseConnection(con); } } public static void end() { commit(); } public static void rollback() { ConnectionHolder holder = null; Connection con = null; try { holder = getConnectionHolder(); holder.setRollback(true); con = holder.getConnection(); if (holder.isIsreadonly()) { throw new RuntimeException("readonly cannot rollback...."); } con.rollback(); con.setAutoCommit(true); } catch (RuntimeException e) { throw e; } catch (Exception e) { logger.error("", e); } finally { safeCloseConnection(con); } } private static ConnectionHolder getConnectionHolder() { ConnectionHolder holder = (ConnectionHolder) _thread.get(); if (null != holder) return holder; throw new RuntimeException("connection holder not exist......."); } public static Connection openConnection() { Connection con = getConnectionHolder().getConnection(); if (null != con) return con; throw new RuntimeException("connection not exist......."); } } Action 部分代码 public ActionForward deleteResourceXqzy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { try { TransactionManager.begin(); //事务开始 /** 多次DAO代码调用 业务处理 多次DAO代码调用 */ } catch (Exception ex) { TransactionManager.rollback(); //事务回滚 //其它操作 } finally { TransactionManager.end(); //事务提交 //其它操作 } return mapping.findForward("test"); } DAO 部分代码 public static void deleteResourceZyfb() throws Exception { String sql = null; PreparedStatement ps = null; try { Connection con = TransactionManager.openConnection(); sql = ""; ps = con.prepareStatment(sql); ps.executeUpdate(); } finally { safeCloseStatementOrRs(ps); } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-02-23
如果以上是成熟的,无线程安全性问题,也可以考虑实现一个TransactionTemplate,代码类似下面这个.
TransactionTemplate public void execute() throws Exception{ try { TransactionManager.begin(); process(); }catch(Exception ex){ TransactionManager.rollback(); throw e; }finally{ TransactionManager.end(); } } abstract protected void process() throws Exception{} Action 部分代码 public ActionForward deleteResourceXqzy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { try { new TransactionTemplate() { public void process() { } }.execute(); } catch (Exception ex) { } return mapping.findForward("test"); } 其实Spring已经有了很完善的功能,不过目前不想对老系统使用Spring!还望大家多给意见,哪些设计的不合理,尤其是线程安全性方面的.当然上面的代码并没有对异常体系进行设计!还是比较习惯使用Exception和RuntimeException这两个异常. |
|
返回顶楼 | |
发表时间:2007-02-27
jamesby 写道 如果以上是成熟的,无线程安全性问题,也可以考虑实现一个TransactionTemplate,代码类似下面这个.
TransactionTemplate public void execute() throws Exception{ try { TransactionManager.begin(); process(); }catch(Exception ex){ TransactionManager.rollback(); throw e; }finally{ TransactionManager.end(); } } abstract protected void process() throws Exception{} Action 部分代码 public ActionForward deleteResourceXqzy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { try { new TransactionTemplate() { public void process() { } }.execute(); } catch (Exception ex) { } return mapping.findForward("test"); } 其实Spring已经有了很完善的功能,不过目前不想对老系统使用Spring!还望大家多给意见,哪些设计的不合理,尤其是线程安全性方面的.当然上面的代码并没有对异常体系进行设计!还是比较习惯使用Exception和RuntimeException这两个异常. 你把ConnectionHolder绑到ThreadLocal 然后每次再去new一个ConnectionHolder再绑一次? |
|
返回顶楼 | |
发表时间:2007-02-27
to JAVA_ED:
什么意思,能否详细说明一下? 不new ConnectionHolder()那用同一个ConnectionHolder? |
|
返回顶楼 | |
发表时间:2007-02-27
jamesby 写道 to JAVA_ED:
什么意思,能否详细说明一下? 不new ConnectionHolder()那用同一个ConnectionHolder? nested transaction? 所谓ConnectionHolder应该是个Connection Container 如果每次begin都去新开个connection, 那前一次的不是丢失了吗 这样不如把connection直接绑上去 |
|
返回顶楼 | |
发表时间:2007-02-27
JAVA_ED 写道 jamesby 写道 to JAVA_ED:
什么意思,能否详细说明一下? 不new ConnectionHolder()那用同一个ConnectionHolder? nested transaction? 所谓ConnectionHolder应该是个Connection Container 如果每次begin都去新开个connection, 那前一次的不是丢失了吗 这样不如把connection直接绑上去 但是我的使用代码是这样的啊,也就是每个Service Method 只使用一个Connection! public ActionForward methodName(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { try { TransactionManager.begin(); //事务开始 /** 多次DAO代码调用 业务处理 多次DAO代码调用 */ } catch (Exception ex) { TransactionManager.rollback(); //事务回滚 //其它操作 } finally { TransactionManager.end(); //事务提交 //其它操作 } return mapping.findForward("test"); } 第一个版本我是将Connection绑上去的,但是后来多了readonly和rollback两个状态,所以弄了这个Holder的. |
|
返回顶楼 | |
发表时间:2007-02-27
jamesby 写道 JAVA_ED 写道 jamesby 写道 to JAVA_ED:
什么意思,能否详细说明一下? 不new ConnectionHolder()那用同一个ConnectionHolder? nested transaction? 所谓ConnectionHolder应该是个Connection Container 如果每次begin都去新开个connection, 那前一次的不是丢失了吗 这样不如把connection直接绑上去 但是我的使用代码是这样的啊,也就是每个Service Method 只使用一个Connection! public ActionForward methodName(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { try { TransactionManager.begin(); //事务开始 /** 多次DAO代码调用 业务处理 多次DAO代码调用 */ } catch (Exception ex) { TransactionManager.rollback(); //事务回滚 //其它操作 } finally { TransactionManager.end(); //事务提交 //其它操作 } return mapping.findForward("test"); } 第一个版本我是将Connection绑上去的,但是后来多了readonly和rollback两个状态,所以弄了这个Holder的. ServiceA(){ try{ begin(); ServiceB(); ..... } } 你可以去参考一下一些OpenSrc Project的TransactionManager如何实现 |
|
返回顶楼 | |
发表时间:2007-02-28
JAVA_ED 写道 ServiceA(){ try{ begin(); ServiceB(); ..... } } 你可以去参考一下一些OpenSrc Project的TransactionManager如何实现 事务有三个方面要考虑,隔离级别、传递方式和readonly,隔离级别目前默认,传递方式就是楼上说的这个. 这样的情况还没有考虑,如果考虑目前的想法是加入一个计数器,begin 时 count++,rollback 时 如果 count>1 throw exception count--,否则rollback, commit时如果count>1 count-- 否则commit. 项目现在紧急,没有时间,我考虑的是TransactionManager这个类的接口稳定,至于如何是最合理最优化的实现,以后再说,先弄个Demo类的东西先跑起来. |
|
返回顶楼 | |
发表时间:2007-04-09
正在做毕业设计,不想引入Spring,时间不够,学不过来。
就借用下!! PS:我会保留版权信息的!呵呵! |
|
返回顶楼 | |
发表时间:2007-04-12
有个问题,在end的同时,是否应该ThreadLocal.remove()呢?
|
|
返回顶楼 | |