【问题标题】:Validate object existence before deletion or update in Spring/Hibernate在 Spring/Hibernate 中删除或更新之前验证对象是否存在
【发布时间】:2011-08-20 13:27:10
【问题描述】:

我正在为我的项目使用 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); 
}

关键是我只想在提到的情况(完整性违规和类似情况)的情况下抛出带有适当消息的友好异常。

【问题讨论】:

    标签: spring hibernate validation dao


    【解决方案1】:

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

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

    编辑(基于问题说明):

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

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

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

    【讨论】:

    • 再次感谢您的回答和对像我这样的初学者的耐心。我得到了你的建议,但我认为我解决这个问题的方法有点天真。我只想在特定情况下抛出一些友好的异常。我改变了我的问题,因为起初我没有描述我的问题出现的背景。
    • 看来你刚刚达到了我的奋斗目标。由于我的 Flex/Spring/Hibernate 应用程序中存在延迟初始化问题,我已经阅读了有关 Open Session in View 方法的内容。对于通信,我使用带有 BlazeDS 集成的 AMF 远程协议,这也使我的 OSiV 实施情况更加复杂。看起来(因为我的截止日期快到了),我可能会放松存在验证和类似的,并尽量减少每操作会话反模式的后果。
    猜你喜欢
    • 1970-01-01
    • 2018-08-05
    • 2012-09-11
    • 2021-03-14
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    • 1970-01-01
    • 2020-07-25
    相关资源
    最近更新 更多