假设我们有一个旧的 Book 和 Authors 模型,两者都有 CRUD。当用户试图删除作者时,我想告诉她如果作者已经注册了书籍,她必须先删除作者的书籍。
也就是说,我只想删除一条记录,除非它没有任何引用,但如果有,我只想警告用户。
第一种方法:
到目前为止我一直在做的方式是这样的:
@PersistenceContext
private EntityManager em;
public void deleteAuthor(Author author){
Long qtBooks = em.createQuery(
"SELECT COUNT(b) FROM Book b WHERE b.author.id = :id")
.setParameter("id", author.getId()).getSingleResult();
if (qtBooks > 0) {
throw IllegalArgumentException("This author has books registered");
}
em.remove(em.getReference(Author.class, author.getId()));
}
...并且在表示层(JSF bean)中,我捕获了异常,IllegalArgumentException
在这种情况下是异常,并向用户显示其错误消息。
第二种方法:
当我使用 Spring 时,我知道另一种方法是DataIntegrityViolationException
在表示层中捕获 Spring's 。然后,业务方法将只包含删除实体的代码:
public void deleteAuthor(Author author){
em.remove(em.getReference(Author.class, author.getId()));
}
...然后表示层(在我的例子中是一个 JSF bean)可以捕获 Spring 异常:
@ManagedProperty("#{authorService}");
private AuthorService authorService;
public void deleteAuthor(Author author) {
try {
authorService.deleteAuthor(author);
addGlobalInfo("Author deleted");
} catch (DataIntegrityViolationException e) {
addGlobalError("This author already has books associated");
}
redirect(getRequestURL());
}
现在,我使用第一种方法已经有一段时间了,我发现第二种方法更容易编写。我的问题是,除了使用这个特定的异常使我的应用程序更依赖于 Spring 之外,使用第二种方法的缺点是什么?第一个的真正优点是什么?到底好不好?是否有第三种更好的方法来使用 JPA 执行此操作?
由于这两种方法都依赖于捕获一些异常(除了第一个在尝试更改数据库中的任何内容之前抛出),我真的不知道如何决定。