但我想从具体问题中恢复,而且我不确定使用未经检查的异常的最佳方法。以下是一个具体的例子。
假设我有一个 Web 应用程序,使用 Struts2 和 Hibernate 构建。如果异常冒泡到我的“操作”,我会记录它,并向用户显示一个漂亮的道歉。但是,我的 Web 应用程序的一个功能是创建需要唯一用户名的新用户帐户。如果用户选择已存在的名称,则 Hibernate 在我的系统内部抛出 org.hibernate.exception.ConstraintViolationException(未经检查的异常)。我真的很想通过要求用户选择另一个用户名来从这个特定的问题中恢复,而不是给他们相同的“我们记录了您的问题,但现在您被卡住了”的消息。
以下是几点需要考虑的:
1.有很多人同时创建帐户。我不想在“SELECT”查看名称是否存在和“INSERT”之间锁定整个用户表。对于关系数据库,可能有一些技巧可以解决这个问题,但我真正感兴趣的是预先检查异常不起作用的一般情况,因为存在基本竞争条件。同样的事情可能适用于在文件系统上查找文件等。
2.鉴于我的 CTO 喜欢通过阅读“Inc.”中的技术专栏进行管理,我需要在持久性机制周围添加一层间接层,以便我可以丢弃 Hibernate 并使用 Kodo 等而不改变除持久性代码最低层之外的任何内容。实际上,在我的系统中有几个这样的抽象层。如何防止它们泄漏,尽管存在未经检查的异常?
3.已声明的检查异常的一个公开的弱点是必须在堆栈上的每个调用中“处理”它们-通过声明调用方法抛出它们或捕获它们并处理它们。处理它们通常意味着将它们包装在适合于抽象级别的类型的另一个检查异常中。因此,在检查异常领域中,基于文件系统的 UserRegistry 的实现可能会捕获 IOException,而数据库实现则会捕获 SQLException,但两者都将抛出一个隐藏底层实现的 UserNotFoundException。如何利用未经检查的异常,使自己免于在每个层次包装的负担,并避免泄漏实现细节?