java - 删除删除时发生分离实例错误

标签 java spring hibernate rest

当我尝试从 REST Controller 中删除以下 Customer 对象时,出现“删除分离的实例”异常。

日志:

org.springframework.dao.InvalidDataAccessApiUsageException: Removing a detached instance com.test.model.Customer#1750; nested exception is java.lang.IllegalArgumentException: Removing a detached instance com.test.model.Customer#1750

域名:

@Entity
public class Customer{

@Id
private Long id;

@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name="COUNTRY_ID", nullable=false)
private Country country;

// other stuff with getters/setters

}

REST Controller :

@Controller
@RequestMapping("/shop/services/customers")
public class CustomerRESTController {

   /**
     * Deletes a customer
     */
    @RequestMapping( value="/{id}", method=RequestMethod.DELETE)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteCustomer(@PathVariable Long id, HttpServletRequest request, HttpServletResponse response) throws Exception {

        Customer customer = customerService.getById(id);
        if(customer != null){
            customerService.delete(customer);
        }else{
            response.sendError(503, "No Customer found for ID : " + id);
        }
    }

    // other stuff
}

我正在从数据库获取客户对象,但仍然 hibernate 提示。 有什么建议吗??

最佳答案

实体在当前 session (或更好的事务)中分离。由于您处于 Spring 内部,因此使用 Java Transaction Service (JTS) 是很常见的。对于交易行为。这样,Hibernate 会在提交后自动清除持久性上下文(就像用作 JPA 解决方案时一样)。

通常 Hibernate 不会清除 session 的持久性上下文,因此您的实体在提交后通常不会分离。 (这在分布式环境中是不安全的,但如果仅使用Hibernate访问数据库并使用Ehcache等分布式缓存,则可以保存)。

解决方案:session.merge(object) 将实体重新附加到当前 session 对象的持久化上下文。

它实际上不是合并,而是重新附加,如果 Hibernate 不确定实体的当前状态是否反射(reflect)了正确的数据库缓存,它将重新加载实体。 (并在出现版本属性(@Version)时添加特殊行为)。

顺便说一句,Hibernate 的文档指出:

Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded.

更新

查看您的代码后,这看起来像是一个事务问题。请检查您的 customerService.getById(id) 和 customerService.delete(customer) 服务调用是否导致事务提交。您需要将两者放在同一个交易中。

您还可以做的一件事也可以解决您的问题:

public void deleteCustomer(@PathVariable Long id, HttpServletRequest request, HttpServletResponse response) throws Exception {
    boolean wasDeleted = customerService.delete(id);
    if(!wasDeleted)
        response.sendError(503, "No Customer found for ID : " + id);
    }
}

这样您就不需要两次服务调用。实际上,在高级服务调用中使用 hibernate 实体并不常见(但对于不同的架构,这可能会有所不同。我不太使用 Spring)。

关于java - 删除删除时发生分离实例错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19078264/

相关文章:

java - 将实例变量传递给静态方法——并修改另一个实例变量?

spring - 如何在单页应用程序(spring security)中提供 CSRF Token?

java - org.hibernate.NonUniqueObjectException。到底是什么原因呢?

java - 将 json id 反序列化为对象列表

sql - 这个在 SELECT 中带有子查询的 SQL 可以转换为 Hibernate 3.0.5 HQL 吗?

java - Platform.runLater 问题 - 延迟执行

Java 多态行为

java - GameManager 类型类的单一职责原则

java - MongoDB 和 Spring MVC : PATCH operation?

java - Hibernate 无法添加或更新子行 : a foreign key constraint fails