【问题标题】:Hibernate - How to retrieve affected IDs list after query updateHibernate - 如何在查询更新后检索受影响的 ID 列表
【发布时间】:2020-10-30 07:40:39
【问题描述】:

我检查了这个解决方案,但它不适用于我的情况 - https://stackoverflow.com/a/47987528/351903

我正在使用 Mysql。

如果我执行以下操作 -

Session session = em.unwrap(Session.class);
    
    Query query = em.createNativeQuery("UPDATE Table tr SET tr.status=:newStatus WHERE tr.status=:oldStatus and tr.processAfter<now()");
    query.setParameter("newStatus", 0);
    query.setParameter("oldStatus",1);
    query.executeUpdate();
List<Table> empList = query.list();  //I get undefined method error - Error:(513, 57) java: cannot find symbol symbol:   method list()  location: variable query of type javax.persistence.Query


    List<Table> empList = query.getResultList(); //can't do this on dml case

我用 getResultList() 得到了这个异常 -

2020-07-09 21:53:46:850 [Thread-10][] DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper[line:124] [] - could not extract ResultSet [n/a]
java.sql.SQLException: Can not issue data manipulation statements with executeQuery().
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:965) ~[mysql-connector-java-5.1.45.jar:5.1.45]
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:898) ~[mysql-connector-java-5.1.45.jar:5.1.45]
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:887) ~[mysql-connector-java-5.1.45.jar:5.1.45]
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:861) ~[mysql-connector-java-5.1.45.jar:5.1.45]
        at com.mysql.jdbc.StatementImpl.checkForDml(StatementImpl.java:469) ~[mysql-connector-java-5.1.45.jar:5.1.45]
        at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1923) ~[mysql-connector-java-5.1.45.jar:5.1.45]
        at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52) ~[HikariCP-2.7.8.jar:?]
        at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java) ~[HikariCP-2.7.8.jar:?]
        at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:60) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.loader.Loader.getResultSet(Loader.java:2168) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1931) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1893) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.loader.Loader.doQuery(Loader.java:938) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.loader.Loader.doList(Loader.java:2692) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.loader.Loader.doList(Loader.java:2675) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2507) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.loader.Loader.list(Loader.java:2502) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2161) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:1016) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:152) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1414) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at org.hibernate.query.Query.getResultList(Query.java:146) [hibernate-core-5.2.14.Final.jar:5.2.14.Final]
        at com.project.service.Service.Method(Service.java:514) [classes/:?]
        

【问题讨论】:

    标签: java hibernate dml


    【解决方案1】:

    如果您正在使用支持此功能的数据库,您可以使用 Blaze-Persistence,这是一个在 JPA/Hibernate 之上运行的库,它增加了对此的支持。

    这里有更多相关信息:https://persistence.blazebit.com/documentation/core/manual/en_US/index.html#returning-from-update-statement

    由于您使用的是 MySQL,我认为最好的方法如下:

    1. 创建一个 SELECT 查询,获取受影响对象的 ID 并使用悲观锁定
    2. 根据 ID 进行更新
    3. (可选)根据 id 获取您需要的任何数据

    不幸的是,这是 MySQL 所能做的最好的事情。在某些时候,Blaze-Persistence 会添加一个实现此方案的仿真,因此您不必考虑如何去做,但性能模型仍然会与您的预期不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-29
      • 2018-06-07
      • 2012-02-11
      • 2022-10-15
      • 1970-01-01
      • 2013-02-16
      • 1970-01-01
      相关资源
      最近更新 更多