论坛首页 Java企业应用论坛

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

浏览 9348 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-10-08  
DAO

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

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

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

//结合spring支持hibernate
Session 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...);
    }
}

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

 

 

 

   发表时间:2008-10-08  
你既然选择了这样一种分离的模式,DAO中就不应该包含过多的业务逻辑,甚至不应该包含任何业务逻辑只关心(Data Access)。特别是不应该为了你自己模块的实用性,而抛弃整个借口的适用性,那样,分层的意义也就没有了。
感觉你是在为了分层而分层。

# public List update###(){ 
#            dao.get(s); 
#            dao.update##(String ...); 
#            dao.delete##(String ...); 
#            dao.insert##(String ...); 
#            return dao.find##(String...); 
#    }  

这段代码,不知道你怎么保证会在一个事务里完成。
0 请登录后投票
   发表时间:2008-10-08  
个人觉得,这个是蛮常见的现象,在做Web层代码的时候(就是你这里所说的action),很容易会把业务逻辑相关的代码都完成了。原因其实很简单,因为把Web交互的代码和业务逻辑代码混淆了。

把Service层做厚,确实要花费不少时间,想想SOA的概念,这个是一个代码结构逐渐调整的概念。

再来看一下DAO层,会发现你的Service层的薄,DAO层也是罪魁祸首之一。应该把事务控制在Service层,而不是在DAO层。

DAO层提供的接口,应该是简单的数据操作接口,而不应该包含复杂的业务逻辑在里面。
0 请登录后投票
   发表时间:2008-10-08  
chhj_292 写道

感觉你是在为了分层而分层。

# public List update###(){ 
#            dao.get(s); 
#            dao.update##(String ...); 
#            dao.delete##(String ...); 
#            dao.insert##(String ...); 
#            return dao.find##(String...);
//处理更复杂的业务逻辑。
#    }  

public void logice(){
  //to do something
}

这段代码,不知道你怎么保证会在一个事务里完成。


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

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


顺便说一下:我刚才仔细的看了without EJB关于事务的那张。明确了我一个模糊的概念,就是SPRING的声明事务会对所调用业务方法进行拦截,也就是对它调用的DAO方法处在同一个事务中。
0 请登录后投票
   发表时间:2008-10-08  
taopian 写道

     把Service层做厚,确实要花费不少时间,想想SOA的概念,这个是一个代码结构逐渐调整的概念。


我现在的工作是检查其他同学写的代码,找出代码中有臭味的地方,优化这个系统。其实,这工作很痛苦。希望大家给我优化系统更好的建议。谢谢!
1 请登录后投票
   发表时间:2008-10-09  
http://www.iteye.com/topic/87426?page=1看了这篇我明白了--我用的两种方法其实都用的是同一个session(Connection).
0 请登录后投票
   发表时间:2008-10-09  
你用了hibernate然后又调用jdbc处理...
0 请登录后投票
   发表时间:2008-10-10  
laiseeme 写道
你用了hibernate然后又调用jdbc处理...

有些简单的处理用HIbernate来处理就可以了,但复杂的查询用JDBC来处理会比较好点,也比较好控制。
0 请登录后投票
   发表时间:2008-10-10  
对的,事务发起后,session是绑定到ThreadLocal的,所以……

而且通常需要用opensessioninview filter(你们也用了吧),所以即便你action里分多次调用service,也还是用的同一个session,占用资源的时间只会更长,而且这样调用service会导致事务不一致
0 请登录后投票
   发表时间:2008-10-10  
daquan198163 写道
session是绑定到ThreadLocal的,你再怎么分层也是一样的

恩了,
那么象比较负责的业务处理通常你们是怎么做的呢?

事务尽快尽早的结束,也就是优化程序,优化SQL。那么具体怎么优化呢?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics