首页 > 解决方案 > org.hibernate.hql.internal.QueryExecutionRequestException:不支持不使用休眠的 DML 操作

问题描述

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

实体是这样创建的:

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

@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 工件,因为我没有 Modifying 注释。IE

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

好吧,我现在确实拥有它,但仍然不允许删除查询。

如果我稍微更改代码并使用休眠来删除行,那么一切正常,但在这种情况下这不是一个骗局删除,而且速度很慢。即,如果我将整个属性作为对象传递,并在集合端直接调用休眠会话时为每个循环执行一次,那么它就可以工作。

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

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

标签: javahibernatehql

解决方案


这与Modifying. Modifying是一个 Spring Data 注释,但你似乎没有使用 Spring Data。

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

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

JavaDoc 指出:

执行更新或删除语句。


推荐阅读