Expected behavior: DuplicateKeyException should be thrown Actual behavior: TransientDataAccessResourceException is thrown
Workaround (perhaps not ideal, but I imagine this should work reasonably well in practice): When catching TransientDataAccessException, rethrow (wrapped) as DuplicateKeyException when exception message contains "Attempt to insert duplicate key row"
Versions: - SAP (Sybase) Adaptive Server Enterprise version 16 SP03 PL11 - jconn 4.2 - spring-jdbc 6.1.14 - spring-boot 3.3.5 - java 17
Sample stack trace:
org.springframework.dao.TransientDataAccessResourceException: StatementCallback; SQL [insert into foo...]; JZ0BE: BatchUpdateException: Error occurred while executing batch statement: Attempt to insert duplicate key row in object 'foo' with unique index 'foo_idx'
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:124) ~[spring-jdbc-6.1.14.jar:6.1.14]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:107) ~[spring-jdbc-6.1.14.jar:6.1.14]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:116) ~[spring-jdbc-6.1.14.jar:6.1.14]
at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1548) ~[spring-jdbc-6.1.14.jar:6.1.14]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:408) ~[spring-jdbc-6.1.14.jar:6.1.14]
at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:632) ~[spring-jdbc-6.1.14.jar:6.1.14]
...
Caused by: java.sql.BatchUpdateException: JZ0BE: BatchUpdateException: Error occurred while executing batch statement: Attempt to insert duplicate key row in object 'foo' with unique index 'foo_idx'
at com.sybase.jdbc42.jdbc.ErrorMessage.raiseBatchUpdateException(ErrorMessage.java:1404) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.jdbc.SybStatement.batchLoop(SybStatement.java:2410) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.jdbc.SybStatement.sendBatch(SybStatement.java:2190) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.jdbc.SybStatement.executeBatch(SybStatement.java:2148) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.jdbc.SybStatement.executeBatch(SybStatement.java:1950) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.zaxxer.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:127) ~[HikariCP-5.1.0.jar:?]
at com.zaxxer.hikari.pool.HikariProxyStatement.executeBatch(HikariProxyStatement.java) ~[HikariCP-5.1.0.jar:?]
at jdk.internal.reflect.GeneratedMethodAccessor69.invoke(Unknown Source) ~[?:?]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.base/java.lang.reflect.Method.invoke(Method.java:569) ~[?:?]
at net.ttddyy.dsproxy.proxy.StatementProxyLogic.performQueryExecutionListener(StatementProxyLogic.java:316) ~[datasource-proxy-1.8.1.jar:?]
at net.ttddyy.dsproxy.proxy.StatementProxyLogic.access$700(StatementProxyLogic.java:37) ~[datasource-proxy-1.8.1.jar:?]
at net.ttddyy.dsproxy.proxy.StatementProxyLogic$1.execute(StatementProxyLogic.java:123) ~[datasource-proxy-1.8.1.jar:?]
at net.ttddyy.dsproxy.listener.MethodExecutionListenerUtils.invoke(MethodExecutionListenerUtils.java:42) ~[datasource-proxy-1.8.1.jar:?]
at net.ttddyy.dsproxy.proxy.StatementProxyLogic.invoke(StatementProxyLogic.java:120) ~[datasource-proxy-1.8.1.jar:?]
at net.ttddyy.dsproxy.proxy.jdk.StatementInvocationHandler.invoke(StatementInvocationHandler.java:34) ~[datasource-proxy-1.8.1.jar:?]
at jdk.proxy3/jdk.proxy3.$Proxy127.executeBatch(Unknown Source) ~[?:?]
at org.springframework.jdbc.core.JdbcTemplate$1BatchUpdateStatementCallback.doInStatement(JdbcTemplate.java:592) ~[spring-jdbc-6.1.14.jar:6.1.14]
at org.springframework.jdbc.core.JdbcTemplate$1BatchUpdateStatementCallback.doInStatement(JdbcTemplate.java:578) ~[spring-jdbc-6.1.14.jar:6.1.14]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:393) ~[spring-jdbc-6.1.14.jar:6.1.14]
... 24 more
Caused by: com.sybase.jdbc42.jdbc.SybSQLException: Attempt to insert duplicate key row in object 'foo' with unique index 'foo_idx'
at com.sybase.jdbc42.tds.Tds.processEed(Tds.java:4230) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.tds.Tds.nextResult(Tds.java:3347) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.jdbc.ResultGetter.nextResult(ResultGetter.java:78) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.jdbc.SybStatement.nextResult(SybStatement.java:308) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.jdbc.SybStatement.batchLoop(SybStatement.java:2248) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.jdbc.SybStatement.sendBatch(SybStatement.java:2190) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.jdbc.SybStatement.executeBatch(SybStatement.java:2148) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.sybase.jdbc42.jdbc.SybStatement.executeBatch(SybStatement.java:1950) ~[jconn-4.2.jar:JDK 1.8/jdbcdev/Tuesday, October 12, 2021 08:07:21 PM PDT]
at com.zaxxer.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:127) ~[HikariCP-5.1.0.jar:?]
at com.zaxxer.hikari.pool.HikariProxyStatement.executeBatch(HikariProxyStatement.java) ~[HikariCP-5.1.0.jar:?]
at jdk.internal.reflect.GeneratedMethodAccessor69.invoke(Unknown Source) ~[?:?]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.base/java.lang.reflect.Method.invoke(Method.java:569) ~[?:?]
at net.ttddyy.dsproxy.proxy.StatementProxyLogic.performQueryExecutionListener(StatementProxyLogic.java:316) ~[datasource-proxy-1.8.1.jar:?]
at net.ttddyy.dsproxy.proxy.StatementProxyLogic.access$700(StatementProxyLogic.java:37) ~[datasource-proxy-1.8.1.jar:?]
at net.ttddyy.dsproxy.proxy.StatementProxyLogic$1.execute(StatementProxyLogic.java:123) ~[datasource-proxy-1.8.1.jar:?]
at net.ttddyy.dsproxy.listener.MethodExecutionListenerUtils.invoke(MethodExecutionListenerUtils.java:42) ~[datasource-proxy-1.8.1.jar:?]
at net.ttddyy.dsproxy.proxy.StatementProxyLogic.invoke(StatementProxyLogic.java:120) ~[datasource-proxy-1.8.1.jar:?]
at net.ttddyy.dsproxy.proxy.jdk.StatementInvocationHandler.invoke(StatementInvocationHandler.java:34) ~[datasource-proxy-1.8.1.jar:?]
at jdk.proxy3/jdk.proxy3.$Proxy127.executeBatch(Unknown Source) ~[?:?]
at org.springframework.jdbc.core.JdbcTemplate$1BatchUpdateStatementCallback.doInStatement(JdbcTemplate.java:592) ~[spring-jdbc-6.1.14.jar:6.1.14]
at org.springframework.jdbc.core.JdbcTemplate$1BatchUpdateStatementCallback.doInStatement(JdbcTemplate.java:578) ~[spring-jdbc-6.1.14.jar:6.1.14]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:393) ~[spring-jdbc-6.1.14.jar:6.1.14]
... 24 more