Spring 数据 JDBC @Modifying with PostgreSQL 从已修改行返回 return 数据
Spring Data JDBC @Modifying with PostgreSQL RETURNING to return data from modified rows
PostgreSQL 提供了一种从 DML 语句 return 数据的简洁方法,请参阅 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[=14=](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[=14=](JdbcTemplate.java:867)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
... 95 more
Spring 数据 JDBC 指出修改查询只能 return 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 但我想采用 Spring 方式。
当您使用 @Modifying
注释该方法时,它会作为 DML 语句执行,该语句不会 return 除了更新的行数之外的任何值。
如果你的语句 return 是 ResultSet
你不应该使用 @Modifying
,所以 Spring 数据 JDBC 尝试提取 ResultSet
并从中为方法创建 return 值。
PostgreSQL 提供了一种从 DML 语句 return 数据的简洁方法,请参阅 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[=14=](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[=14=](JdbcTemplate.java:867)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
... 95 more
Spring 数据 JDBC 指出修改查询只能 return 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 但我想采用 Spring 方式。
当您使用 @Modifying
注释该方法时,它会作为 DML 语句执行,该语句不会 return 除了更新的行数之外的任何值。
如果你的语句 return 是 ResultSet
你不应该使用 @Modifying
,所以 Spring 数据 JDBC 尝试提取 ResultSet
并从中为方法创建 return 值。