代码之家  ›  专栏  ›  技术社区  ›  Sandeepan Nath

Hibernate-如何在查询更新后检索受影响的ID列表

  •  0
  • Sandeepan Nath  · 技术社区  · 5 年前

    我检查了这个解决方案,但它不适用于我的情况- 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/:?]
            
    
    0 回复  |  直到 5 年前
        1
  •  0
  •   Christian Beikov    5 年前

    如果您使用的是支持此功能的数据库,那么可以使用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将添加一个实现此方案的仿真,因此您不必考虑如何实现它,但性能模型仍将与您预期的不同。