java—将数据库异常信息传输到客户端的最佳实践

vc6uscn9  于 2021-07-12  发布在  Java
关注(0)|答案(2)|浏览(309)

我有一个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它们吗?
谢谢你的建议。

3bygqnnd

3bygqnnd1#

热释光;博士
java/hibernate/spring组合无法提供有用的异常对象。在应用程序级别,要向用户提供有意义的错误描述是非常困难的。
仅仅从异常链本身,几乎不可能得到像“name is already used”这样有意义的东西。请选择另一个”。
有这么多层将异常 Package 到其他异常中,因此您需要一个ai来查找“问题描述”。
即使是最具体的例外情况 java.sql.SQLIntegrityConstraintViolationException 只包含一个文本原因,不适合最终用户,并且没有任何内容可用于提取导致冲突的字段。我能看到的唯一提示是导致问题的值的重复。
但我建议不要对文本进行如此重要的值或字段名解析。即使它与您当前的设置一起工作,在下一个版本中,您的数据库使用不同的原因文本模板,您也会迷失方向。
如果您不想编写大量的异常分析代码,可以将预期的异常类型转换为泛型描述,如
java.sql.sqlintegrityconstraintviolationexception:“数据库完整性检查:您输入的某些值可能已在数据库中使用”。
这通常可以在rest服务的顶层完成。
如果这还不够好,我只看到在代码中实现异常分析的可能性:
在您知道sql语句含义的地方捕获异常,
根据预期的故障可能性进行一些查询,以找出可能的原因,例如查询数据库中是否存在名称,
将原始异常 Package 成更有意义的异常,例如包含故障模式的异常 ALREADY_USED ,字段名 "name" 和字段值 "Aktenzeichen XY0000000000000003333333333444444444245555555555f" .

fivyi3re

fivyi3re2#

一开始, @NotNull 类似的约束应该在控制器级别进行验证。在它到达应用程序的其他层之前,进行强验证和消毒。如果出现错误,则返回http status 400 bad request,并可能添加有意义的错误消息。
在将条目保存到数据库之前,请检查条目是否存在。对于现有条目,返回http status 409 conflict并可能形成有意义的消息。
其他错误,如 SQLIntegrityConstraintViolationException 应导致http status 500内部服务器错误,带有模糊消息“internal server error”,而不会向客户端公开数据库/服务器/底层异常详细信息。
例如,使用spring检查rest的错误处理。

相关问题