首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

细粒度处理事务,抓紧的结束事务

2012-10-31 
细粒度处理事务,尽快的结束事务????? 在搭建系统的架构时我们采用了ssh+ajax等方式构建的。我一在和大家说

细粒度处理事务,尽快的结束事务

????? 在搭建系统的架构时我们采用了ssh+ajax等方式构建的。我一在和大家说我们要层次分明,思路清晰,可现在都比较糟糕。

?????? 比如:JSP页面用来显示数据的,css用来美化页面,JS用来控制页面的。现在很多页面中什么都有了,臭味很多。

?????? 在后台我们也分了action,service,dao层,原本action用来控制调度的,service用来处理相关的业务逻辑的,DAO中用来CRUD数据的。可现在出现了action包裹着一部分逻辑,service就非常简单了,就是用来调用DAO中的方法,而DAO中的方法即包裹了业务处理逻辑又包裹了CRUD数据处理。而且有的业务逻辑非常的复杂,涉及到的表操作很多,比如有

//结合spring支持hibernateSession session = getSession();//可以能会处理的一些东西//1)通过hibernate方法select数据//2)通过hibernate方法update数据//3)通过hibernate方法delete数据//4)通过hibernate方法insert数据//通过session获取Connection,使用JDBC进行数据处理Connection con = session.getConnection();//因为有一些逻辑很负责一个select语句涉及的表太多,所以用JDBC来处理。String sql = "select a ,b ,c ,d from A ,B,C,D where a = ? and b=?";//反正类似的操作吧,就是关连来多。

?类似上面的方式,大多数同学在大多数的时候都是这么弄的。我觉得这样做就把业务逻辑和数据处理混淆了,方法太臃肿了,有着浓浓的臭味,不便于维护。XP中提倡面向接口编程、分层、短小的方法。它这么一个长长的方法占用一个连接的时间太长(也就是整个事务的时间延长了),那么当其他的用户对相关的表进行请求时,就会出于等待的状态,资源的竞争,如果长时间是这样死锁就出现了。:(

?

???? 我一般会把他们分布在不同的方法中。

//对应表的相关操作public interface DAO{     public List get##(String s);     public void update##(String ...);     public void delete##(String ...);     public void insert##(String ...);     public List find##(String...);}public class Service{    public DAO dao = .......;//注入DAO对象。    //结合DAO执行相应的业务处理操作    public List update###(){           dao.get(s);           dao.update##(String ...);           dao.delete##(String ...);           dao.insert##(String ...);           //处理更复杂的业务逻辑。           logice();           return dao.find##(String...);   }     public void logice(){            //to do something    }    }

?这样我的每一个DAO中的方法就会用到不同的SESSION(不同的CONNECTION),是这样的吗?但是我是通过SPRING对service层进行事务处理的呀,那是不是说明两种方式都会要占用同样的事务处理资源?

?

???? 看到那些贫血的SERVICE我就郁闷,现在我有检查代码是否存在问题我也迷茫,这事情做的太少了。很多时候我们只顾一直往前跑,没有时间回头看。其实,我们要经常的code view,使用TDD开发模式,用XP的小步发布,这样不要让代码的味道变的太坏,也对自己写的代码充满信心,和用户交流底气十足。开发出来的系统,用户满意,市场行情看涨。:)

请您提出宝贵的意见。

?

?

更新:2008-10-10 22:00

?

我把标题从“DAO实现方法中一个Connection捅到底好吗?头疼”改成“细粒度处理事务,尽快的结束事务”,这个是我最终的目的。现在我明白了整个业务方法调用过程中都是使用同一个SESSION(Connection)。至于业务逻辑怎样来平衡分布,是不是可以把一部分放到ACTION,一部分放到service,Dao只负责和数据库处理。对只读的事务我对其只用readOnly。

比如:我上面的例子是不是可以变成如下的样子呢?

//对应表的相关操作public interface DAO{     public List get##(String s);     public void update##(String ...);     public void delete##(String ...);     public void insert##(String ...);     public List find##(String...);}public class Service{    public DAO dao = .......;//注入DAO对象。    //结合DAO执行相应的业务处理操作    //该方法上加事务,传播途径为required    public void update###(){                     dao.update##(String ...);           dao.delete##(String ...);           dao.insert##(String ...);           //处理更复杂的业务逻辑。           logice();   }        //该方法上加事务,传播途径为required,readOnly   public  String get###(String s){          return dao.get(s);   }     //该方法上加事务,传播途径为required,readOnly   public List find###(String...){          return dao.find##(String...);   }    public void logice(){            //to do something    }    }/***那么action中是不是可以变成如下的样子呢?**/public class Action{     //注入服务类     public Service service = null;     public ActoinForward update###(ActionForm...............){           //下面这样调用是不是会能更好的呢?            service. get###(s);            service. update###();            service. find###(String...);    }}

?? 我们希望能够更快的结束事务,避免不必要的阻塞,保证系统有更好的性能。

?

?

?

public void logice(){ //to do something}
这段代码,不知道你怎么保证会在一个事务里完成。

当然了“public List update###()”这个方法中还有其它的业务处理逻辑,或者会在sevice类中定义相关的方法吧。

我用SPRING的声明事务,对SERVICE层进行事务拦截。


顺便说一下:我刚才仔细的看了without EJB关于事务的那张。明确了我一个模糊的概念,就是SPRING的声明事务会对所调用业务方法进行拦截,也就是对它调用的DAO方法处在同一个事务中。
<script src="/javascripts/tinymce/plugins/javaeye/langs/zh.js" type="text/javascript"></script>
,JS用来控制页面的。现在很多页面中什么都有了,臭味很多。</p>
<p>?????? 在后台我们也分了action,service,dao层,原本action用来控制调度的,service用来处理相关的业务逻辑的,DAO中用来CRUD数据的。可现在出现了action包裹着一部分逻辑,service就非常简单了,就是用来调用DAO中的方法,而DAO中的方法即包裹了业务处理逻辑又包裹了CRUD数据处理。而且有的业务逻辑非常的复杂,涉及到的表操作很多</p>
</div>
<p>action要做到delegate到service,也要fill到view中,包含部分逻辑也是合理的。</p>
<p>dao方法中包含部分业务逻辑也是合理的,这个是充血domian object的做法,hibernate也支持的很好,也不是不合理的...</p>
<p>?</p>
<p>楼主用的dao和hiberante orm持久对象应该是贫血模型吧?</p> 16 楼 kyo100900 2008-10-14   hgq0011 写道daquan198163 写道而且通常需要用opensessioninview filter(你们也用了吧),
  我们没有用它,也是考虑到一个请求处理有时会占用很长的时间所以没有用它。

因为系统在某些时间段并发量大,业务有比较复杂,所以要优化程序优化SQL,具体有什么好的建议吗?谢谢



如果并发量大,业务复杂(可能是一个长事务)的话,hibernate提供的乐观锁机制可以一定程度上缓解数据库的压力。
17 楼 fangwei 2008-10-27   在我曾经做过的系统中遇到过与楼主同样的问题,我既希望在操作失败时能回滚数据库,但又不希望长时间锁住一个表(这里在并发多时会出现性能问题,也就是楼主说的阻塞)。

1.首先也是想到了将原本在1个service中的多个dao分解到不同的service中,然后在action中调用多个service(我们也是将事务声明在了service层)。这样做使用了多个数据库连接,的确能在一定程度上避免阻塞,但在一个会话中创建多个数据库连接是比较耗费资源的(使用连接池可能会好一点),更重要的是事务也不好控制。比如你的dao顺序是:
select
update
select
delete
select。

2.因为在spring框架中没有找到更好的事务配置办法,后来采用了硬编码处理sql异常来控制事务。上面的多个dao还是放在1个service中,取得连接并将使用其默认的自动提交属性设置true(即执行完一个dao就提交),分别处理各个dao抛出的异常,执行相应的dao以保持数据的一致性(相当于回滚数据库)。这样做使得锁住一个表的时间缩短从而降低了阻塞发生的几率,而且只创建1个数据库连接降低了资源耗费,缺点是编码太过繁琐,例如update还得保存之前的值用以回滚。

最后权衡了一下系统的实际情况,系统在内网使用,数据库在局域网,在一次会话过程中发生数据库异常的可能性非常小,所以,像这种情况的service,我选择了性能,放弃了事务。不知道大侠们都是如何处理这种service的? 18 楼 sdh5724 2008-10-29   我说的是大规模的并发环境下意见, 每天有千万以上PV的站点:
1.绝对禁止使用声明式事务
2.小心手动控制事务处理, 处理好数据准备工作, 尽量把事务在最小的代码块里完成.

这么说吧, 大规模并发环境中, 使用手动事务比声明式事物性能高3-5倍<通过长期观察得出的结论>. 而且声明事物容易发生死锁行为.
最终的解决方案, 对于基于服务的应用. 自己做事务服务器. 我知道有站点这么作的. 我目前也在做哈, 不然SOA类型的应用, 想控制事务太困难.  哈.

19 楼 风花雪月饼 2008-10-29   sdh5724 写道我说的是大规模的并发环境下意见, 每天有千万以上PV的站点:
1.绝对禁止使用声明式事务
2.小心手动控制事务处理, 处理好数据准备工作, 尽量把事务在最小的代码块里完成.

这么说吧, 大规模并发环境中, 使用手动事务比声明式事物性能高3-5倍<通过长期观察得出的结论>. 而且声明事物容易发生死锁行为.
最终的解决方案, 对于基于服务的应用. 自己做事务服务器. 我知道有站点这么作的. 我目前也在做哈, 不然SOA类型的应用, 想控制事务太困难.  哈.


真会这么高效么?
声明事务覆盖的方法中如果只有一个数据库操作我觉得有没有事务都一样的。
从Spring的文档上看,似乎不是很推荐手动控制,说这样就造成了入侵性还是什么。但是说也有特殊情况。
其实我也整不明白,为什么就一个insert的方法也得声明事务。这不是找茬么。。。比如save(Entity entity)里面很简单的最终调用了HibernateTemplate.save。也是事务。 20 楼 fangwei 2008-11-11   风花雪月饼 写道
真会这么高效么?
声明事务覆盖的方法中如果只有一个数据库操作我觉得有没有事务都一样的。
从Spring的文档上看,似乎不是很推荐手动控制,说这样就造成了入侵性还是什么。但是说也有特殊情况。
其实我也整不明白,为什么就一个insert的方法也得声明事务。这不是找茬么。。。比如save(Entity entity)里面很简单的最终调用了HibernateTemplate.save。也是事务。

同意,一个insert的方法确实不需要声明事务。

热点排行