java - org.hibernate.hql.internal.QueryExecutionRequestException : Not supported for DML operations without using hibernate

标签 java hibernate hql

我有一个基于 2.1.0.RELEASE 的 Spring Boot 应用程序,并使用 hibernate 5.3.7.Final 进行大多数交互 到数据库,除了几种情况,我想删除对象列表,因此我想执行一个批量删除该列表的方法。我已经可以使用普通的 hql 查询将 getBulk 作为列表执行,因此 我想对删除进行同样的操作,因为它要快得多。

实体的创建方式如下:

我有一个表属性,它一对一映射到名为值的表。 值表只有一种关系,即与属性

@Repository
@Entity
@Table(name="ATTRIBUTE")
@OnDelete(action=OnDeleteAction.CASCADE)
public class Attribute implements AttributeInterface {

    .......

    @OneToOne(cascade=CascadeType.ALL, orphanRemoval=true)
    @ElementCollection(fetch=FetchType.EAGER)
    @JoinColumn(name="VALUE_ID", nullable=false)
    @OnDelete(action=OnDeleteAction.CASCADE)
    private Value valueId;
}

来自 postgres:

\d attribute;
                              Table "public.attribute"
         Column          |           Type           | Collation | Nullable | Default 
-------------------------+--------------------------+-----------+----------+---------                           
 id                      | bytea                    |           | not null | 
 .......
 value_id                | bigint                   |           | not null | 
 .......

Indexes:
    "attribute_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    .......
    "fksc44hph1sm89gdg2o01bjiuad" FOREIGN KEY (value_id) REFERENCES value(id) ON DELETE CASCADE

存储库方法使用 @Transactional 和 @Modifying 注释显式注释。我的服务类中也有 @Transactional 注释调用删除。

@Transactional
@Modifying
@Override
public void delete(Collection<byte[]> list) {


    try {


        Session session = getSessionFactory().openSession();
        session.beginTransaction();

        session.flush();
        session.clear();


        String hql_query = "DELETE from Attribute as o WHERE o.id IN (:ids)";
        Query<?> query = session.createQuery(hql_query);

        query.setParameterList("ids", list);
        query.list();



        session.getTransaction().commit();
        session.close();


    } catch (Exception e) {
        logger.error("Exception", e);
        throw e;
    }
}

这给了我错误

java.lang.IllegalStateException: org.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML operations [DELETE from org.Attribute as o WHERE o.id=:ids]
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1508)

这里和这里描述了这个确切的异常 https://www.javabullets.com/spring-data-jpa-query-not-supported-for-dml-operations/

在互联网上我读到了我需要的

org.springframework.data.jpa.repository.Modifying

注释。 我必须添加额外的依赖项,即 spring-data-jpa artifacat,因为我没有修改注释。即

<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
</dependency>

嗯,我现在已经有了,但仍然没有 允许删除查询。

如果我稍微更改代码并使用 hibernate 删除行,那么一切都会起作用,但在这种情况下这不是恶意删除,而且速度很慢。 即,如果我将整个属性作为对象传递,并在集合端直接调用 hibernate session 上执行每个循环,那么它就可以工作。

    session.delete(attribute);
    session.getTransaction().commit();
    session.close();

我的问题是我在批量删除方法中做错了什么。我在这里缺少什么吗?

最佳答案

这与修改无关。 Modifying 是一个 Spring Data 注释,但您似乎没有使用 Spring Data。

您正在执行query.list()它用于执行返回结果的选择语句。

由于您尝试执行删除,因此需要使用 executeUpdate()

JavaDoc 对此进行了说明:

Execute the update or delete statement.

关于java - org.hibernate.hql.internal.QueryExecutionRequestException : Not supported for DML operations without using hibernate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53579891/

相关文章:

java - SWIG 在为 Java 包装 C++ 时显示错误

java - 在 Struts2 中使用 prepare() 方法在 action 类中执行 CRUD 操作

java - 为什么 JpaRepository 在保存实体时尝试为空 FK 键创建实体?

sql - 更改默认列值会导致 Hibernate 出现问题吗?

java - 如何绘制球体的中半部分(在代码中)

java - Java 中的一元增量符++x 和x++

mysql - 连接表并找到最小值/最大值(集合)

java - 按日期升序排序,最后为空

java - 在 Hibernate 中自动生成带有注释的字符串主键

java - 如何编写 HQL 查询来处理可选输入参数