在Spring/Hibernate中删除或更新之前验证对象是否存在

slo*_*mir 5 validation spring dao hibernate

我在项目中使用Spring/Hibernate组合,使用标准的CRUD操作.

我想知道,在删除或更新之前验证对象存在是否合理?如果是,哪里是最合适的地方 - 服务还是dao层?

编辑:
对不起,当我问这个问题时,我没有说明问题.存在检查的唯一动机是向服务客户端抛出友好的异常(没有DAO特定).

问题是我必须做'存在检查,因为我的服务方法是事务性的,除此之外,我正在使用HibernateTemplate和DaoSupport助手类在DAO对象中进行会话操作.

根据提到,Hibernate异常(例如在删除不存在的实例的情况下)在提交时抛出,这是我无法实现的,因为(我想)提交是由代理对象中的PlatformTransactionManager执行的,我没有机会在我的服务方法中处理该异常并向客户端重新抛出一些友好的异常.

但是,即使我在删除之前保持我的策略检查存在,但是在实例存在的情况下,我遇到了NonUniqueObjectException问题,因为我重新附加(在删除时间内)已经加载的实例(在读取时间内存在)检查).

例如:

//Existence checking in this example is not so important
public void delete(Employee emp){  
    Employee tempEmp=employeeDao.read(emp.getId());  
    if(tempEmp==null)  
        throw new SomeAppSpecificException();  
}  
//Existence checking in this example is maybe 'more logical'    
public void save(Assignment a){  
    Task t=taskDao.read(a.getTask().getId());
    if(t==null)  
        throw new FriendlyForeignKeyConstraintException(); 
    Employee e=employeeDao.read(a.getEmployee().getId());  
    if(e==null)  
        throw new EmployeeNotFoundExc();
    //...some more integrity checking and similar...  
    assignmentDao.save(a); 
}
Run Code Online (Sandbox Code Playgroud)

关键是我只想在上述情况(完整性违规和类似情况)中使用适当的消息抛出友好异常.

Chs*_*y76 3

在 Hibernate 术语中,更新和删除操作(以及Session上的相应方法)都处理持久化实体。因此,它们的存在是隐含的,并且在代码中再次验证它是毫无意义的 - Hibernate 将自行执行此操作,如果情况并非如此,则会抛出异常。然后您可以捕获并处理(或重新抛出)该异常。

附带说明(基于您的示例代码),无需显式读取您要删除的实例。Session 提供了load()方法,该方法将返回适合传递给delete()方法的代理实例,而无需实际访问数据库。它假定与给定 PK 关联的实例存在,如果情况不存在,稍后将会失败(抛出异常)。

编辑(基于问题澄清):

当您说要向客户端抛出“友好”异常时,“友好”和“客户端”的定义变得很重要。在大多数现实生活场景中,您的事务将不仅仅跨越您的服务之一上的简单原子“save()”或“delete()”方法。

如果客户端是本地的,并且您不需要在单个客户端交互中进行单独的事务(典型场景 - Web 应用程序在具有服务层的同一 VM 中运行),那么通常最好在那里启动/提交事务(请参阅在以下位置打开会话)例如,查看)。然后,您可以在提交期间捕获并正确处理(包括包装/重新抛出,如果需要)异常。其他场景更复杂,但最终异常将传播到您的“顶级”客户端;只是如果您需要以“友好”的方式向客户展示“根本”原因,那么打开它可能会很复杂。

但最重要的是,这取决于您。如果您宁愿因自己的异常而快速失败(以编写一些样板代码为代价),那么这并没有什么问题。