无法捕获服务层中的异常

时间:2015-07-17 14:09:39

标签: hibernate rest exception try-catch

我有一个REST Web应用程序 在名为ThingGroup的资源上执行PUT请求时,我的控制器会像那样调用服务层

@RequestMapping(method = RequestMethod.PUT)
@ResponseBody
public void updateThingGroup(@Valid @RequestBody final ThingGroup thingGroup, final Principal principal) throws UnknownResourceException {
    final User user = userService.findByUserName(principal.getName());
    thingGroupService.update(thingGroup, user);
}

相应的thingGroupService @Transactional

@Override
@Transactional
public ThingGroup update(final ThingGroup thingGroup, User user){
    ThingGroup found = null;
    try {
        found = find(thingGroup.getId(),user);

        found.setName(thingGroup.getName());

        found = getDao().save(found);

    } catch (final DataIntegrityViolationException e) {

        // I want to throw that custom exception here

        MyBadRequestException ex = new MyBadRequestException("MyBadRequestException.update.violation.thingGroup", "violation_data_integrity");
        ex.setParameters(new Object[] { thingGroup.getName()});
        throw ex;
    }
    return found;
}

在MySQL底层数据库中,我对thingGroup的名称有一个unicity约束。

因此,如果我尝试使用现有名称更新thingGroup,它应该会失败。

当它失败时,我想抛出一个自定义异常,将可理解的消息传递给控制器​​层。

我的问题是,由于@Transactional注释,在提交事务后抛出Hibernate异常,这意味着在返回服务方法之后(我认为)。

这意味着我无法在服务层中捕获异常。

我已经搜索过这样的答案,正如我所理解的,我需要在Controller层中捕获异常。然而,它似乎不是一个好的解决方案,因为控制器层必须知道服务层的基本行为,这是不好的。

这个问题有一些通用的解决方案吗?

2 个答案:

答案 0 :(得分:1)

您可以手动flush对数据库的修改,以强制在事务结束时发生的自动刷新之前发生约束违规。

答案 1 :(得分:0)

最简单的解决方案是将实际事务从此服务方法移出到单独的方法中。这样就可以在离开服务方法之前提交事务,并且可以对Hibernate异常做出反应。

@Override
public ThingGroup update(final ThingGroup thingGroup, User user){
    ThingGroup found = null;
    try {
        return doUpdate(thingGroup, user)
    } catch (final DataIntegrityViolationException e) {
        // I want to throw that custom exception here
        MyBadRequestException ex = new MyBadRequestException("MyBadRequestException.update.violation.thingGroup", "violation_data_integrity");
        ex.setParameters(new Object[] { thingGroup.getName()});
        throw ex;
    }
    return found;
}

@Transactional
public ThingGroup doUpdate(final ThingGroup thingGroup, User user){
    ThingGroup found = find(thingGroup.getId(),user);
    found.setName(thingGroup.getName());
    found = getDao().save(found);
    return found;
}

这里的方法doUpdate是公开的

一个。更简单的单元测试和

湾如果你不使用方面,可以使用交易。