You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用带嵌入式ID的JPA实体删除数据库行失败排查

问题描述

我正在开发一款基于Java的后端应用,技术栈包含JPA、Rest、Hibernate、Spring Boot。当关联的Item被删除时,我调用deleteParameterById方法删除Parameter记录,日志显示参数ID已正确传入,但Swagger测试始终返回“Data Was Not Found”提示。这是我首次尝试删除带Embedded Id的实体记录,查询无法正常执行。

现有代码

删除方法(JPQL版本)

@Override
@Transactional
public void deleteParameterById(Long parameterId) {
    Query query = entityManager
     .createQuery("DELETE FROM ParameterEntity pa WHERE pa.ParameterEntityId.parameterId = ?1");
     query.setParameter(1, parameterId)
     .executeUpdate();
}

嵌入式ID类(ParameterEntityId.java)

@Embeddable
public class ParameterEntityId implements Serializable {
  @Column(name = "PARAMETER_ID")
  private Long parameterId;

  @Column(name = "PARAMETER_ATTRIBUTE_TYPE_ID")
  private Long parameterAttributeTypeId;
}

实体类(ParameterEntity.java)

@Entity
@Table(name = "parameter")
public class ParameterEntity {
  @EmbeddedId
  private ParameterEntityId parameterEntityId;

  @Column(name = "VALUE")
  private String value;
}

原生SQL版本删除方法

@Override
@Transactional
public void deleteParameterById(Long parameterId) {
      entityManager.createNativeQuery("DELETE FROM *dbname(redacted)*.parameter WHERE parameter_id = ?1")
      .setParameter(1, parameterId).executeUpdate();
}

我查阅的示例多采用JPA Repository实现,但本应用未配置该方式。用原生SQL尝试删除时,请求一直处于“processing”状态,已确认应用具备表的编辑与删除权限。

请问哪里操作出错了?


问题分析与解决

1. JPQL查询的核心错误

JPQL中引用实体属性必须严格匹配Java代码的变量名大小写:你的实体类里嵌入式ID字段是parameterEntityId(小写p开头),但查询语句里写的是pa.ParameterEntityId.parameterId(大写P开头),这会导致Hibernate无法识别该属性,查询找不到任何匹配数据,最终返回“Data Was Not Found”。

修正后的JPQL删除代码:

@Override
@Transactional
public void deleteParameterById(Long parameterId) {
    Query query = entityManager
     .createQuery("DELETE FROM ParameterEntity pa WHERE pa.parameterEntityId.parameterId = ?1");
     query.setParameter(1, parameterId)
     .executeUpdate();
}

2. 原生SQL查询的阻塞问题

原生SQL请求一直处于“processing”状态,主要有两个可能原因:

  • 语法错误:SQL里的*dbname(redacted)*写法不符合数据库规范,比如MySQL应直接写DELETE FROM dbname.parameter,去掉星号;
  • 事务或锁等待:检查@Transactional注解的传播机制是否正确,确保方法在有效事务中执行;同时排查数据库是否存在未释放的行锁,比如其他事务占用了待删除数据的锁,导致当前请求阻塞。

3. 调试验证方案

如果还是无法定位问题,可以先查询再删除,明确数据是否存在:

@Override
@Transactional
public void deleteParameterById(Long parameterId) {
    // 先查询匹配记录
    List<ParameterEntity> entities = entityManager.createQuery(
        "SELECT pa FROM ParameterEntity pa WHERE pa.parameterEntityId.parameterId = ?1",
        ParameterEntity.class
    ).setParameter(1, parameterId).getResultList();
    
    if (!entities.isEmpty()) {
        entities.forEach(entityManager::remove);
    } else {
        throw new RuntimeException("Data Was Not Found");
    }
}

这种方式能直观确认是否存在待删除数据,方便排查逻辑问题。


内容的提问来源于stack exchange,提问作者Mtullis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 18:13:13