2

PostgreSQL provides a neat way to return data from DML statements, see https://www.postgresql.org/docs/current/dml-returning.html

What I tried to achieve is something like the following snipped

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

to retrieve the deleted row. However, this leads to the following exception

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 states that a modifying query can return void, int and boolean only, see https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#jdbc.query-methods.at-query.modifying

Adding a custom RowMapper leads to the same exception.

    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);

Is there an option to achieve this?

Edit: I am aware of plain JDBC https://stackoverflow.com/a/40787385/1239904 but I would like to go with the Spring way.

1 Answer 1

3

When you annotate the method with @Modifying it is executed it is executed as a DML statement which does not return any value except the number of rows updated.

If your statement returns a ResultSet you should not use @Modifying, so Spring Data JDBC tries to extract the ResultSet and create return values for the method from it.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. Works as you described it. However, are there really no negative side-effects of omiting @Modifying?
@Modifying changes the method called on the JDBC driver and the way results get processed. That's all.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.