Hibernate - How to retrieve affected IDs list after query update

允我心安 提交于 2020-07-23 07:34:26

问题


I checked this solution but it did not work for my case - https://stackoverflow.com/a/47987528/351903

I am working with Mysql.

If I do the following -

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

I get this exception with 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/:?]
        

回答1:


If you were working with a database that supports this, you could use Blaze-Persistence, a library that works on top of JPA/Hibernate, which adds support for this.

Here some more information about that: https://persistence.blazebit.com/documentation/core/manual/en_US/index.html#returning-from-update-statement

Since you are using MySQL, I think the best way to do this is the following:

  1. Create a SELECT query that fetches the ids of the affected object and use pessimistic locking
  2. Do your updates based on the ids
  3. (optional) Fetch any data that you need based on the ids

That's the best that can be done with MySQL unfortunately. At some point, Blaze-Persistence will add an emulation that implements this scheme, so you don't have to think about how to do it, but still, the performance model will be different than what you'd expect.



来源:https://stackoverflow.com/questions/62819457/hibernate-how-to-retrieve-affected-ids-list-after-query-update

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!