MyBatis映射器直接注入服务类。例外呢?

时间:2012-01-04 14:29:10

标签: java spring design-patterns dao mybatis

我目前正在使用MyBatis-Spring集成框架,这就是我从文档中读到的内容:

  

不是使用SqlSessionDaoSupport或SqlSessionTemplate手动编写数据访问对象(DAO),   Mybatis-Spring提供了一个代理工厂:MapperFactoryBean。此类允许您注入数据映射器接口   直接进入你的服务bean。使用地图制作工具时,您只需将它们称为“你一直打电话给你”   DAO,但您不需要编写任何DAO实现代码,因为MyBatis-Spring将为其创建代理   你。

这是一个非常好的功能......但是异常处理呢?我应该在哪里翻译SQL错误?在我的服务层?但它不会违反服务DAO模式吗?

示例:

public final class AccountServiceImpl implements AccountService {
(...)
    private AccountMapper accountMapper;
(...)
    @Override
    public void addAccount(Account account) throws AccountServiceException {

       //Validating, processing, setting timestamps etc.
       (...)

       //Persistence:
       int rowsAffected;
       try {
            rowsAffected = accountMapper.insertAccount(account);
       } catch (Exception e) {
            String msg = e.getMessage();
            if (msg.contains("accounts_pkey"))
                throw new AccountServiceException("Username already exists!");
            if (msg.contains("accounts_email_key"))
                throw new AccountServiceException("E-mail already exists!");
            throw new AccountServiceException(APP_ERROR);
       }

       LOG.debug("Rows affected: '{}'", rowsAffected);

       if (rowsAffected != 1)
            throw new AccountServiceException(APP_ERROR);
    }

在服务层中翻译异常是否可以?

应该怎么做?

先谢谢你的建议。

2 个答案:

答案 0 :(得分:7)

最近我使用mybatis-spring进行了一个项目,我遇到了同样的绊脚石。我也不想在DAO异常处理中丢弃我的服务类,特别是因为我的服务层中的某些方法需要对许多不同的表进行只读访问。

我遇到的解决方案是捕获服务层中的异常,但是创建自己的异常类型,将捕获的异常作为参数。然后,这可以过滤掉实际构造异常时应包含的错误消息类型,并消除对字符串匹配的需要(至少在服务层中)。

您接近那里,除了AccountServiceException将有一个以Exception e作为参数的构造函数。我还选择尽早尝试进行所有数据访问,并将其全部包含在一个try / catch中。由于MapperFactoryBean总是将抛出的异常转换为Spring DataAccessExceptions,因此您在进行数据访问时不必担心会遇到其他类型的异常。

我毫不犹豫地将这个问题视为一个答案 - 更多的是经验分享,因为我遇到过这种情况并犹豫不决。

答案 1 :(得分:2)

将MyBatis抛出的低级DataAccessExceptions转换为服务层中的应用程序定义的DataAccessExceptions是一种标准做法。

它通常与事务处理相关联,因为您无法处理跨越DA层中多个DAO的事务。

所以是的,没关系,甚至推荐。

通常我会在错误日志中记录DAO抛出的异常并重新抛出应用程序定义的内容。