我有一个spring-boot-hibernate-mysql微服务和一个通过rest访问服务的web客户端。
我已经通过hibernate注解实现了一些数据库验证。。。e、 g.不为空或唯一。
现在,当验证发现一个错误时,我会得到如下stacktrace:
Caused by: org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a];
constraint [rahmenvertraege.UK_lla4el5s0eip4nwn8e3sd1trk]; nested exception is
org.hibernate.exception.ConstraintViolationException: could not execute statement
...
...
...
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
....
...
...
Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry
'Aktenzeichen XY0000000000000003333333333444444444245555555555f' for key 'rahmenvertraege.UK_lla4el5s0eip4nwn8e3sd1trk'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-java-8.0.21.jar:8.0.21]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.21.jar:8.0.21]
...
..
如果我接收异常消息并通过restapi将其传递给客户机,他会得到上面的消息“couldnotexecutestatement;sql[不适用];约束[rahmenvertraege.uk\u lla4el5s0eip4nwn8e3sd1trk]“这不是很有信息。
位于最低位置的嵌套异常是一个有趣的异常“replicate entry'aktenzeichen xy0000000000000003333333444245555555555f'for key'rahmenvertraege.uk\u lla4el5s0eip4nwn8e3sd1trk'”
但我该怎么做呢?总是带着最深的信息?那不脏吗?客户机(或微服务的服务层)如何为客户机转换这些信息?即使deppest消息是可读的,您也不希望在用户界面中显示它。在这里,你想看到类似“name is already used。请选择另一个”。我必须知道所有可能的异常类型并手动Map它们吗?
谢谢你的建议。
2条答案
按热度按时间3bygqnnd1#
热释光;博士
java/hibernate/spring组合无法提供有用的异常对象。在应用程序级别,要向用户提供有意义的错误描述是非常困难的。
仅仅从异常链本身,几乎不可能得到像“name is already used”这样有意义的东西。请选择另一个”。
有这么多层将异常 Package 到其他异常中,因此您需要一个ai来查找“问题描述”。
即使是最具体的例外情况
java.sql.SQLIntegrityConstraintViolationException
只包含一个文本原因,不适合最终用户,并且没有任何内容可用于提取导致冲突的字段。我能看到的唯一提示是导致问题的值的重复。但我建议不要对文本进行如此重要的值或字段名解析。即使它与您当前的设置一起工作,在下一个版本中,您的数据库使用不同的原因文本模板,您也会迷失方向。
如果您不想编写大量的异常分析代码,可以将预期的异常类型转换为泛型描述,如
java.sql.sqlintegrityconstraintviolationexception:“数据库完整性检查:您输入的某些值可能已在数据库中使用”。
这通常可以在rest服务的顶层完成。
如果这还不够好,我只看到在代码中实现异常分析的可能性:
在您知道sql语句含义的地方捕获异常,
根据预期的故障可能性进行一些查询,以找出可能的原因,例如查询数据库中是否存在名称,
将原始异常 Package 成更有意义的异常,例如包含故障模式的异常
ALREADY_USED
,字段名"name"
和字段值"Aktenzeichen XY0000000000000003333333333444444444245555555555f"
.fivyi3re2#
一开始,
@NotNull
类似的约束应该在控制器级别进行验证。在它到达应用程序的其他层之前,进行强验证和消毒。如果出现错误,则返回http status 400 bad request,并可能添加有意义的错误消息。在将条目保存到数据库之前,请检查条目是否存在。对于现有条目,返回http status 409 conflict并可能形成有意义的消息。
其他错误,如
SQLIntegrityConstraintViolationException
应导致http status 500内部服务器错误,带有模糊消息“internal server error”,而不会向客户端公开数据库/服务器/底层异常详细信息。例如,使用spring检查rest的错误处理。