加入设计模式后事务遇到的迷惑,还请各位大哥解难

05-03-09 popufig

在做一个C/S的给老大们演示的例子(一个界面上操作两个主从表,主从表的异动(新增、删除、修改),都要放到同一个事务里),使用了Business Delegate、Service Locator、Session Façade、Transfer Object、Data Access Object几种设计模式,后台数据库是想用CMP做数据的异动(新增、删除、修改),读取数据由DAO或者通过JDBC、Hibernate之类的技术去实现。

DAO我是写了一个接口,然后不同的表实现了不同的DAO接口,然后由Session Façade去调用不同的DAO实现,由于只有两个表,我只写了一个Session Façade,在Session Façade的ejbCreate里注入了DAO的不同实现,由此根据不同的注入可以操作不同的表。

按我的理解,Session Façade应该要分出一定的层次,也就是说假设Session Façade里面底层有方法Amethod、Bmethod、Cmethod,这三个方法是直接操作DAO,而Dmethod是调用了Amethod和Bmethod、Emethod调用了Bmethod和Cmethod,还有可能Fmethod是调用了Dmethod和Emethod,也就是一层一层的叠上去,我理解这样可以提高代码的重用性。然后再由客户端通过Business Delegate调用Session Façade里面的方法。

现在问题来了:

1、在Session Façade和CMP直接加入的DAO是不是多余的呢?(我的考虑是或许以后可以提供不同的实现,保证一定的灵活性)

2、由于我是在Session Façade里的ejbCreate里注入了所需要的DAO实现,也就是说我的Business Delegate在调用Session Façade的时候需要知道我所需要的具体的DAO的实现(至少是要知道实现类的名字),这样是不是会跨层了,按理说Business Delegate只需要知道Session Façade,但是现在还要求他知道DAO的东西,是不是有点...... ,心理总感觉怪怪的。

3、由于要求主从表的异动都要在一个事务里,而且我们不可能一次异动要多次和Session Façade交互,也就是说Session Façade里需要一次帮我们搞定,这样子似乎刚才的ejbCreate注入DAO的实现根本不能用了(因为有可能操作两个DAO),而且Session Façade里会因为刚才我们需要的一次到位的方法,在Session Façade出现越来越多的层次(这时候似乎Facade里面的分层成了一个累赘)。

4、事务该在哪里进行控制,DAO肯定是不可能,而Session Façade里由于考虑了重用性和客户端的需要分了很多的层次,里面的各个层次都很可能在以后会被Business Delegate调用,所以在Session Façade进行事务控制似乎也不行??

我该怎么做?请大家各抒己见,多多发表自己的观点和意见!!

第一次在jdon发帖子,希望大家多多支持,谢谢!!!

wtusmchen
2005-03-10 08:46

CS的咚咚还用java做??你花10分力也没有用vc、delphi花一分力做出来的好用,个人认为java不适合在pc上面跑,window一统江湖的情况下还是写win32的程序吧^_^

SportsBaby1980
2005-03-10 10:21

Dao你写了一个接口?

好象还不行

你要做一个标识性接口:来区别Dao和其他类

这个接口可以什么都不做

但你的Dao要实现这个接口或你的Dao接口继承这个接口

popufig
2005-03-10 11:06

我的代码是这样的:

DAO接口:

public interface DAOBase {

  public ValueObject findByPrimaryKey(Object pPrimaryKey)
      throws DataAccessException, NoDataFoundException,
      ServiceLocatorException;

  public void insert(ValueObject pValueObject,Collection col)
      throws DataAccessException,ServiceLocatorException;

  public void update(ValueObject pValueObject)
      throws DataAccessException,ServiceLocatorException;

  public void delete(Integer PK)
      throws DataAccessException,ServiceLocatorException;


}
<p>

分别对两个表实现的接口:

public class pCgcodeGDAO implements DAOBase{

  public ValueObject findByPrimaryKey(Object pPrimaryKey)
      throws DataAccessException, NoDataFoundException,
      ServiceLocatorException
      {
        ValueObject vo = new PCgCodeKVO();
        try{
          Integer pkPrimatyKey = (Integer) pPrimaryKey;
          ServiceLocator serviceLocator = ServiceLocator.getInstance();

          PCgcodeGHome pCgcodeGHome =
              (PCgcodeGHome) serviceLocator.getEJBLocalHome(ServiceLocator.
              PCGCODE_G);
          PCgcodeG pCgcodeg = pCgcodeGHome.findByPrimaryKey(pkPrimatyKey);
          vo = pCgcodeg.getVO();
        }catch(Exception e)
        {
          return null;
        }finally
        {
            return vo;
        }

      }

  public void insert(ValueObject pValueObject,Collection col)
      throws DataAccessException,ServiceLocatorException
  {
    try{
      ServiceLocator serviceLocator = ServiceLocator.getInstance();

      PCgcodeGHome pCgcodeGHome =
          (PCgcodeGHome) serviceLocator.getEJBLocalHome(ServiceLocator.
          PCGCODE_G);
      pCgcodeGHome.create(pValueObject,null);
    }catch(Exception e)
    {

    }finally
    {

    }

  }

  public void update(ValueObject pValueObject)
      throws DataAccessException,ServiceLocatorException
  {
    try{
      PCgCodeGVO vo = (PCgCodeGVO)pValueObject;
      Integer pkPrimatyKey = new Integer(vo.getP_CgCode_G_ID());
      ServiceLocator serviceLocator = ServiceLocator.getInstance();

      PCgcodeGHome pCgcodeGHome =
          (PCgcodeGHome) serviceLocator.getEJBLocalHome(ServiceLocator.
          PCGCODE_G);
      PCgcodeG pCgcodeg = pCgcodeGHome.findByPrimaryKey(pkPrimatyKey);
      pCgcodeg.setVO(vo);
    }catch(Exception e)
    {

    }finally
    {

    }

  }

  public void delete(Integer pCgcodeGId)
      throws DataAccessException,ServiceLocatorException
  {
    try{
      ServiceLocator serviceLocator = ServiceLocator.getInstance();

      PCgcodeGHome pCgcodeGHome =
          (PCgcodeGHome) serviceLocator.getEJBLocalHome(ServiceLocator.
          PCGCODE_G);
      PCgcodeG pCgcodeg = pCgcodeGHome.findByPrimaryKey(pCgcodeGId);
      pCgcodeg.remove();
    }catch(Exception e)
    {

    }finally
    {

    }

  }

}

<p>

由于还是在设计阶段,里面的异常没有处理

另一个DAO的实现类似,也就不贴出来了

Session Facade:

public class PCgcodeFacadeBean
    implements SessionBean {
  SessionContext sessionContext;
  DAOBase voEntity;

  public void ejbCreate(DAOBase dao) throws CreateException {
    this.voEntity = dao;
  }

  public void ejbRemove() {
  }

  public void ejbActivate() {
  }

  public void ejbPassivate() {
  }

  public void setSessionContext(SessionContext sessionContext) {
    this.sessionContext = sessionContext;
  }

  public void setDAOBase(DAOBase dao)
  {
    this.voEntity = dao;
  }
  public void saveNewData(ValueObject vo)
  {
    this.saveNewData(vo,null);
  }

  public void updateData(ValueObject vo)
  {
    try{
      voEntity.update(vo);
    }catch(Exception e)
    {

    }
  }

  public void delData(Integer pk)
  {
    try{
      voEntity.delete(pk);
    }catch(Exception e)
    {

    }

  }

  public void saveNewData(ValueObject vo, Collection col)
  {
    try{
      voEntity.insert(vo,col);
    }catch(Exception e)
    {

    }

  }

  public void saveNewDatas(Collection collection) {
    for (Iterator it=collection.iterator(); it.hasNext(); ) {
        ValueObject element = (ValueObject)it.next();
        this.saveNewData(element);
    }
  }

  public void updateDatas(Collection collection) {
    for (Iterator it=collection.iterator(); it.hasNext(); ) {
        ValueObject element = (ValueObject)it.next();
        this.updateData(element);
    }

  }

}

<p>

上面依靠构造注入和set注入不同的DAO实现

问题是现在我好像犯了一个错误,Session Facade里面仅仅是对DAO对象全部方法直接包装起来,而不提供任何额外的抽象。

于是Session Facade显得臃肿不堪。

是不是应该在Session Facade之间加入一层,对DAO进行一定的操作实现一定的业务逻辑?

Session Facade不应该是简单的对DAO对象全部方法直接包装起来,而不提供任何额外的抽象。

看到这两条定义:

“客户机通过把请求发送给 Facade,再由 Facade 把请求转发给适当的子系统对象来与子系统通信。”

“facade 只是对通往子系统对象的接口进行抽象以使它们更易于使用;它不定义新功能。”

我还看到这样的定义:

它们自己不做实际工作;它们委派其它对象做实际工作。这意味着Session facade 中的每个方法都应该很小(异常处理逻辑不计算在内,代码应为五行或更少)。

它们提供简单的接口。这意味着 facade 方法的数量应相对较少(每个Session bean 中仅有约 24 个)。

它们是底层系统的客户端接口。它们应该把特定于子系统的信息封装起来,并且不应该在不必要的情况下公开它。

似乎在我的Session Facade和DAO中间缺少什么东西??

还有Session Facade所谓的分层是不是应该这像下图一样?

这样层次虽然清晰,但是会不会影响性能?我调用最高层的Session Facade会经过好几个调用,虽然是本地调用,这时候性能是不是问题?

popufig
2005-03-10 11:14

晕,代码怎么贴成这样了..

重贴:

DAO接口:

public interface DAOBase {

public ValueObject findByPrimaryKey(Object pPrimaryKey)

throws DataAccessException, NoDataFoundException,

ServiceLocatorException;

public void insert(ValueObject pValueObject,Collection col)

throws DataAccessException,ServiceLocatorException;

public void update(ValueObject pValueObject)

throws DataAccessException,ServiceLocatorException;

public void delete(Integer PK)

throws DataAccessException,ServiceLocatorException;

}

分别对两个表实现的DAO类:

public class pCgcodeGDAO implements DAOBase{

public ValueObject findByPrimaryKey(Object pPrimaryKey)

throws DataAccessException, NoDataFoundException,

ServiceLocatorException

{

ValueObject vo = new PCgCodeKVO();

try{

Integer pkPrimatyKey = (Integer) pPrimaryKey;

ServiceLocator serviceLocator = ServiceLocator.getInstance();

PCgcodeGHome pCgcodeGHome =

(PCgcodeGHome) serviceLocator.getEJBLocalHome(ServiceLocator.

PCGCODE_G);

PCgcodeG pCgcodeg = pCgcodeGHome.findByPrimaryKey(pkPrimatyKey);

vo = pCgcodeg.getVO();

}catch(Exception e)

{

return null;

}finally

{

return vo;

}

}

public void insert(ValueObject pValueObject,Collection col)

throws DataAccessException,ServiceLocatorException

{

try{

ServiceLocator serviceLocator = ServiceLocator.getInstance();

PCgcodeGHome pCgcodeGHome =

(PCgcodeGHome) serviceLocator.getEJBLocalHome(ServiceLocator.

PCGCODE_G);

pCgcodeGHome.create(pValueObject,null);

}catch(Exception e)

{

}finally

{

}

}

public void update(ValueObject pValueObject)

throws DataAccessException,ServiceLocatorException

{

try{

PCgCodeGVO vo = (PCgCodeGVO)pValueObject;

Integer pkPrimatyKey = new Integer(vo.getP_CgCode_G_ID());

ServiceLocator serviceLocator = ServiceLocator.getInstance();

PCgcodeGHome pCgcodeGHome =

(PCgcodeGHome) serviceLocator.getEJBLocalHome(ServiceLocator.

PCGCODE_G);

PCgcodeG pCgcodeg = pCgcodeGHome.findByPrimaryKey(pkPrimatyKey);

pCgcodeg.setVO(vo);

}catch(Exception e)

{

}finally

{

}

}

public void delete(Integer pCgcodeGId)

throws DataAccessException,ServiceLocatorException

{

try{

ServiceLocator serviceLocator = ServiceLocator.getInstance();

PCgcodeGHome pCgcodeGHome =

(PCgcodeGHome) serviceLocator.getEJBLocalHome(ServiceLocator.

PCGCODE_G);

PCgcodeG pCgcodeg = pCgcodeGHome.findByPrimaryKey(pCgcodeGId);

pCgcodeg.remove();

}catch(Exception e)

{

}finally

{

}

}

}

由于还是在设计阶段,里面的异常没有处理

另一个DAO的实现类似,也就不贴出来了

Session Facade:

public class PCgcodeFacadeBean

implements SessionBean {

SessionContext sessionContext;

DAOBase voEntity;

public void ejbCreate(DAOBase dao) throws CreateException {

this.voEntity = dao;

}

public void ejbRemove() {

}

public void ejbActivate() {

}

public void ejbPassivate() {

}

public void setSessionContext(SessionContext sessionContext) {

this.sessionContext = sessionContext;

}

public void saveNewData(ValueObject vo)

{

this.saveNewData(vo,null);

}

public void updateData(ValueObject vo)

{

try{

voEntity.update(vo);

}catch(Exception e)

{

}

}

public void delData(Integer pk)

{

try{

voEntity.delete(pk);

}catch(Exception e)

{

}

}

public Collection findData(int start, int len)

{

return null;

}

public ValueObject findData(int pk)

{

return null;

}

public void saveNewData(ValueObject vo, Collection col)

{

try{

voEntity.insert(vo,col);

}catch(Exception e)

{

}

}

public void saveNewDatas(Collection collection) {

for (Iterator it=collection.iterator(); it.hasNext(); ) {

ValueObject element = (ValueObject)it.next();

this.saveNewData(element);

}

}

public void updateDatas(Collection collection) {

for (Iterator it=collection.iterator(); it.hasNext(); ) {

ValueObject element = (ValueObject)it.next();

this.updateData(element);

}

}

}

上面依靠构造注入和set注入不同的DAO实现

2Go 1 2 下一页