我有一个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层中捕获异常。然而,它似乎不是一个好的解决方案,因为控制器层必须知道服务层的基本行为,这是不好的。
这个问题有一些通用的解决方案吗?
答案 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是公开的
一个。更简单的单元测试和
湾如果你不使用方面,可以使用交易。