处理删除记录期间的错误

时间:2018-08-15 16:50:22

标签: java exception exception-handling

void deleteFilm(@PathVariable(value = "id") Integer id) {
     try {
         filmService.deleteFilm(id);
     }
     catch (ConstraintViolationException e) {
         throw e;
     }
     catch (SQLIntegrityConstraintViolationException ex) {

     }
}

    2018-08-15 18:12:10.075  WARN 8568 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1451, SQLState: 23000
2018-08-15 18:12:10.075 ERROR 8568 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper   : Cannot delete or update a parent row: a foreign key constraint fails (`todo`.`seance`, CONSTRAINT `FKchlcmip8ejlfuo4c990k5ry8y` FOREIGN KEY (`film_id`) REFERENCES `film` (`id`))
2018-08-15 18:12:10.077  INFO 8568 --- [io-8080-exec-10] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements
2018-08-15 18:12:10.080 ERROR 8568 --- [io-8080-exec-10] o.h.i.ExceptionMapperStandardImpl        : HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]
2018-08-15 18:12:10.154 ERROR 8568 --- [io-8080-exec-10] 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 [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`todo`.`seance`, CONSTRAINT `FKchlcmip8ejlfuo4c990k5ry8y` FOREIGN KEY (`film_id`) REFERENCES `film` (`id`))
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_131]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_131]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_131]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_131]

ConstraintViolationException不会捕获错误,并且使用SQLIntegrityConstraintViolationException永远不会被相应的try块抛出

我读到了

java.lang.Object
   java.lang.Throwable
      java.lang.Exception
         java.sql.SQLException
            java.sql.SQLNonTransientException
               java.sql.SQLIntegrityConstraintViolationException
                  com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException

jdbc4.MySQLIntegrityConstraintViolationException继承自SQLEXception,但try块永远不会抛出该异常

1 个答案:

答案 0 :(得分:1)

这是一个编程错误,必须通过选择如何处理外键来纠正。

问题是您要删除父记录,而留下孤立的条目(film_id中的todo.seance引用了影片ID)

您有两个选择

  • 进行级联删除,以便如果删除影片,则也将删除相应的seance记录(由数据库自动完成)。 MySQL关于forein键的文档为here(带有参考选项,其中包括on delete cascade等)
  • 更改应用程序逻辑,以先删除seance的{​​{1}}项,然后再删除父级电影记录。

请记住,您需要明确抛出异常:

film_id