【问题标题】:Cannot catch DataIntegrityViolationException无法捕获 DataIntegrityViolationException
【发布时间】:2018-09-22 12:45:03
【问题描述】:

我正在使用 Spring Boot 2 和 spring-boot-starter-data-jpa 和底层 MariaDB。

我有一个带有唯一键“用户名”的表。如果违反此约束,我想捕获DataIntegrityViolationException,但似乎 Spring 正在记录 DataIntegrityViolationException 并且不会重新抛出后续记录(我的最佳猜测)。 MySQLIntegrityConstraintViolationException 被抛出。

我想在UserService.createUser(..) 中捕获DataIntegrityViolationException

这里有几个sn-ps代码:

@Repository
@Transactional(propagation = Propagation.MANDATORY)
public class UserRepository {

    @PersistenceContext
    private EntityManager entityManager;

    public void save(User user) {
        entityManager.persist(user);
    }
}

@Service
@Transactional(value = Transactional.TxType.REQUIRED)
public class UserService {

@Autowired
private UserRepository userRepository;

private void createUser(User user){
    userRepository.save(user);
}

堆栈跟踪:

2018-09-22 14:20:33.163  WARN 10700 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1062, SQLState: 23000
2018-09-22 14:20:33.163 ERROR 10700 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : Duplicate entry 'kkflf' for key 'user_username_uindex'
2018-09-22 14:20:33.163 ERROR 10700 --- [nio-8080-exec-1] o.h.i.ExceptionMapperStandardImpl        : HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]
2018-09-22 14:20:33.177 ERROR 10700 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [user_username_uindex]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'kkflf' for key 'user_username_uindex'
...

【问题讨论】:

  • try ... catch(DataIntegrityViolationException excp) 包围userRepository.save(user) 不起作用?
  • 很遗憾,这就是我试图开始的。我刚刚解决了这个问题。一旦事务提交,就会抛出异常。这是有道理的。

标签: spring hibernate spring-boot jpa


【解决方案1】:

我解决了这个问题。

在事务提交之前不会发生异常,这很有意义。

我能够在控制器类中捕获事务范围之外的异常。

【讨论】:

  • 谢谢。你是一个绅士和一个学者
【解决方案2】:

正如 kkflf 所说,在 txn 提交之前,通常不会抛出异常。如果你需要它抛出,你可以在该行之后调用flush()。

但是,我已经学会了不依赖它作为任何事情的条件逻辑的艰难方法。例如,我想尝试删除,如果这不起作用,请执行其他操作。但是,如果有任何进一步的数据库活动会涉及该对象(即使是通过引用),系统(spring/hibernate/whathaveyou)将不会喜欢该状态。

正确的流程是在尝试操作之前自己在代码中检查条件。换句话说,不要将数据库用作 IF 语句:-)

// Just say 'no' to this:
if (DB doesn't like it) {
    // do this
} else {
   // do that
}

【讨论】:

    猜你喜欢
    • 2016-09-11
    • 1970-01-01
    • 2016-07-29
    • 2018-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    相关资源
    最近更新 更多