MyBatis 映射器直接注入到服务类中。例外情况如何?
Posted
技术标签:
【中文标题】MyBatis 映射器直接注入到服务类中。例外情况如何?【英文标题】:MyBatis mapper injected directly into service class. What about exceptions? 【发布时间】:2012-02-02 10:47:10 【问题描述】:我目前正在使用 MyBatis-Spring 集成框架,这就是我从文档中看到的内容:
而不是使用 SqlSessionDaoSupport 或 SqlSessionTemplate 手动编写数据访问对象 (DAO), Mybatis-Spring 提供了一个代理工厂:MapperFactoryBean。此类允许您注入数据映射器接口 直接进入您的服务 bean。使用映射器时,您只需调用它们,就像您一直调用的那样 DAO,但您不需要编写任何 DAO 实现,因为 MyBatis-Spring 将为 你。
这是一个非常好的功能......但是异常处理呢?我应该在哪里翻译 SQL 错误?在我的服务层?但这不会违反 service-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);
在服务层翻译异常可以吗?
应该怎么做?
提前感谢您的建议。
【问题讨论】:
【参考方案1】:最近在一个项目中使用了 mybatis-spring,我遇到了同样的绊脚石。我也不想用 DAO 异常处理乱扔我的服务类,特别是因为我的服务层中的某些方法需要对许多不同的表进行只读访问。
我得出的解决方案是在服务层捕获异常,但创建自己的异常类型,将捕获的异常作为参数。这样就可以在实际构造异常时过滤掉应该包含什么样的错误消息,并消除对字符串匹配的需要(至少在服务层中)。
你在那里很接近,除了AccountServiceException
会有一个以Exception e
作为参数的构造函数。我还选择尽可能早地尝试完成所有数据访问,并将其全部包装在一个 try/catch 中。由于 MapperFactoryBean
总是将抛出的异常转换为 Spring DataAccessExceptions
,因此您不必担心在进行数据访问时捕获其他类型的异常。
我犹豫是否将其视为这样的答案 - 考虑到我遇到这个问题并且也犹豫过,更多的是分享经验。
【讨论】:
【参考方案2】:将 MyBatis 抛出的低级 DataAccessExceptions 转换为服务层中应用程序定义的异常是一种标准做法。
它通常与事务处理有关,因为您无法在 DA 层处理跨越多个 DAO 的事务。
所以是的,这没关系,甚至推荐。
通常我将 DAO 抛出的异常记录在错误日志中,然后重新抛出应用程序定义的内容。
【讨论】:
以上是关于MyBatis 映射器直接注入到服务类中。例外情况如何?的主要内容,如果未能解决你的问题,请参考以下文章
mybatis配置好了MapperScannerConfigurer 注入了映射器 为啥启动Tomcat 就报错 一定要我写dao的Impl