我正在开发一个使用 JPA、Rest、Hibernate、Spring Boot 并在后端运行 Java 的应用程序。
我从另一个方法调用此方法,如果有人删除与该参数关联的项目,则会清除记录。 我的日志让我知道参数 ID 正在传递到查询中,因此问题似乎源于查询本身。 当我测试我的代码是 Swagger 时,我只是不断收到“未找到数据”消息。
这是我第一次尝试删除具有嵌入 ID 的记录,但我似乎无法让查询正常工作。我做错了什么?
这是删除方法,我在其中进行查询:
@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;
我发现很多使用 JPA 存储库的示例,但这不是这个应用程序的配置方式,我们使用的是实体。
我最初只是尝试编写一个本机查询并直接调用数据库表Parameters并直接选择parameter_cd,这样我就可以绕过这个嵌入式密钥,(数据库使用parameter_id和parameter_attribute_type_id的复合键)但是当我在 Swagger 中测试它时,我只是收到一条“正在处理”消息,并且查询永远不会完成运行。
我还确保应用程序具有从表中编辑和删除的适当权限。
这是我原来的本机查询:
@Override
@Transactional
public void deleteParameterById(Long parameterId) {
entityManager.createNativeQuery("DELETE FROM *dbname(redacted)*.parameter WHERE parameter_id = ?1")
.setParameter(1, parameterId).executeUpdate();
}
正如 Chris 在评论中已经写的那样,必须使用
parameterEntityId
属性的正确大小写来修复查询,以便您:
Query query =
entityManager.createQuery(
"DELETE FROM ParameterEntity pa WHERE pa.parameterEntityId.parameterId = ?1");
使用您的原始查询,会抛出此异常:
Caused by: org.hibernate.query.sqm.UnknownPathException: Could not resolve attribute 'ParameterEntityId' of 'it.so.entity.ParameterEntity' [DELETE FROM ParameterEntity pa WHERE pa.ParameterEntityId.parameterId = ?1]
at org.hibernate.query.hql.internal.StandardHqlTranslator.translate(StandardHqlTranslator.java:88)
at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.createHqlInterpretation(QueryInterpretationCacheStandardImpl.java:145)
at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.resolveHqlInterpretation(QueryInterpretationCacheStandardImpl.java:132)
at org.hibernate.internal.AbstractSharedSessionContract.interpretHql(AbstractSharedSessionContract.java:802)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:852)
... 49 more
Caused by: org.hibernate.query.sqm.PathElementException: Could not resolve attribute 'ParameterEntityId' of 'it.so.entity.ParameterEntity'
使用正确的查询,Hibernate 将 jpql 转换为以下 sql:
delete from parameter pe1_0 where pe1_0.parameter_id=?
与您的本机匹配,在单元测试执行中立即运行,没有错误。
正如您所说,此查询在 SQLDeveloper 中运行顺利,我怀疑当此查询在应用程序中运行时,可能会锁定在控制器和
deleteParameterById
之间的其余端点调用期间发生的数据库上的记录。方法。我建议检查是否有在此删除方法之前运行的东西可能会创建此锁。
试试这个:
Query query = entityManager
.createQuery("DELETE FROM ParameterEntity pa WHERE pa.ParameterEntityId.parameterId = :paramId");
query.setParameter("paramId", parameterId).executeUpdate();