【问题标题】:Spring Data JDBC @Modifying with PostgreSQL RETURNING to return data from modified rowsSpring Data JDBC @Modifying with PostgreSQL RETURNING 从修改的行返回数据
【发布时间】:2020-11-04 08:53:07
【问题描述】:

PostgreSQL 提供了一种从 DML 语句返回数据的简洁方法,请参阅 https://www.postgresql.org/docs/current/dml-returning.html

我试图达到的效果类似于以下内容

@Modifying
@Query("DELETE FROM Book b WHERE b.title = :title RETURNING *")
Book deleteReturning(@Param("title") String title);

检索已删除的行。 但是,这会导致以下异常

org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [DELETE FROM Book b WHERE b.title = ? RETURNING *]; A result was returned when none was expected.; nested exception is org.postgresql.util.PSQLException: A result was returned when none was expected.
    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:104)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
    at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1443)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633)
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:862)
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:883)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:321)
    at org.springframework.data.jdbc.repository.query.AbstractJdbcQuery.lambda$createModifyingQueryExecutor$0(AbstractJdbcQuery.java:103)
    at org.springframework.data.jdbc.repository.query.StringBasedJdbcQuery.execute(StringBasedJdbcQuery.java:85)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor$QueryMethodInvoker.invoke(QueryExecutorMethodInterceptor.java:195)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130)
    ...
Caused by: org.postgresql.util.PSQLException: A result was returned when none was expected.
    at org.postgresql.jdbc.PgStatement.checkNoResultUpdate(PgStatement.java:269)
    at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:131)
    at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
    at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
    at org.springframework.jdbc.core.JdbcTemplate.lambda$update$0(JdbcTemplate.java:867)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
    ... 95 more

Spring Data JDBC 声明修改查询只能返回 void、int 和 boolean,请参阅 https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#jdbc.query-methods.at-query.modifying

添加自定义 RowMapper 会导致同样的异常。

    public class BookRowMapper<T> implements RowMapper<Book> {
        @Override
        public Book mapRow(final ResultSet rs, final int rowNum) throws SQLException {
            return new Book(rs.getString(1), ...);
        }
    }

    @Modifying
    @Query(value = "delete from Book b where b.title = :title returning *", rowMapperClass = BookRowMapper.class)
    Book deleteReturning(@Param("title") String title);

有没有办法实现这一点?

编辑:我知道普通的 JDBC https://stackoverflow.com/a/40787385/1239904 但我想采用 Spring 方式。

【问题讨论】:

    标签: java postgresql spring-data-jdbc


    【解决方案1】:

    当您使用 @Modifying 注释方法时,它会作为 DML 语句执行,除了更新的行数之外不返回任何值。

    如果您的语句返回 ResultSet,则不应使用 @Modifying,因此 Spring Data JDBC 会尝试提取 ResultSet 并从中为方法创建返回值。

    【讨论】:

    • 谢谢。像你描述的那样工作。但是,省略@Modifying 真的没有负面影响吗?
    • @Modifying 更改了在 JDBC 驱动程序上调用的方法以及处理结果的方式。就是这样。
    猜你喜欢
    • 2021-07-14
    • 2013-07-08
    • 2021-06-28
    • 2021-12-24
    • 2019-05-28
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    相关资源
    最近更新 更多