【发布时间】:2010-05-07 07:32:22
【问题描述】:
我们有一个应用程序需要在创建时检测某些字段中的重复项。我们使用 Hibernate 作为我们的持久层并使用 Spring 的 HibernateTemplate。我的问题是,在创建之前对项目进行预先查找是否更好,或者尝试捕获 DataIntegrityViolation 异常,然后检查这是否是由重复条目引起的。
【问题讨论】:
我们有一个应用程序需要在创建时检测某些字段中的重复项。我们使用 Hibernate 作为我们的持久层并使用 Spring 的 HibernateTemplate。我的问题是,在创建之前对项目进行预先查找是否更好,或者尝试捕获 DataIntegrityViolation 异常,然后检查这是否是由重复条目引起的。
【问题讨论】:
这取决于有重复是一个例外情况,还是一个业务逻辑案例。
例如,在注册期间检查唯一的电子邮件/用户名是一个业务逻辑案例,应该在尝试插入之前完成检查
如果您需要指出哪个字段因唯一约束而失败,您最好事先检查它,而不是捕获异常。捕获异常并不会为您提供重要的细节 - 哪个字段失败。
有办法获取这个信息,根据异常,但是很繁琐,而且是特定于数据库的(在DB中查找约束名(db-specific),得到它应用的字段,匹配具有实体属性的字段)
【讨论】:
最好检查数据库中是否存在数据。检查数据库中是否已存在数据的一种简单方法是让您的类实现 Hibernate LifeCyle api。 Hibernate 允许您在保存之前但在身份与 bean 关联之后验证行为。如果某些逻辑被违反或失败,则可以否决保存操作。
public class Bean extends Serializable implements org.hibernate.classic.LifeCycle {
public boolean onSave(Session s) {
Query query = session.createQuery(from Bean b where b.field=:field");
query.setParameters("field", this.field);
@SuppressWarnings("unchecked")
List<Bean> beans = query.list();
if (beans != null && !beans.isEmpty()) {
// This does not save the identity.
return VETO;
}
return NO_VETO;
}
}
【讨论】:
我肯定会选择 Bozho 的答案。我认为这正是重点。
我目前正在从事的项目中存在类似的问题。我们基于过滤器在多个服务器之间共享信息,并且可能存在接收到的对象已经添加到数据库中的情况,因此会发生 PK 异常。
在我们的案例中,这些 PK 冲突非常罕见,因此我们认为这种情况是例外的。我们还使用 spring 和 hibernate,为了分离这些问题,由于 Springs Transaction-Definitions,我们使用 AOP 来捕获特定的 DataIntegrity-Exception 并重新运行 Transaction,按需进行所需的完整性检查。
如果您在使用 ExceptionHandlerAdvice 时需要帮助,我可以详细说明。
【讨论】: