cannot use `void` for Postgres functions which return `void`
See original GitHub issueMyBatis version
3.5.7
Database vendor and version
PostgreSQL 11.6 (Debian 11.6-1.pgdg90+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit
Postgres JDBC driver: org.postgersql:postgresql:42.2.23
Test case or example project
@Select("SELECT pg_advisory_xact_lock(#{key})")
void lock(@Param("key") long key);
Steps to reproduce
Some of the Postgres advisory locks are functions that return void. The mapper code above breaks with the following error:
Caused by: org.apache.ibatis.executor.ExecutorException: No constructor found in void matching [java.lang.String]
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createByConstructorSignature(DefaultResultSetHandler.java:702)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:658)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:631)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:398)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:355)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:329)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:302)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:195)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:325)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:136)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:151)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:145)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427)
... 37 common frames omitted
The mapper works if we change void
to Void
(from the “primitive” void
, to the object Void
).
But in that case, it always returns a null
, which is not useful.
Expected result
At the very least, Postgres functions (note: functions, not procedures - these things cannot be called with CALL functionName()
) that return void
should be mappable by MyBatis to the void
(lowercase) “primitive” “type” in Java.
Ideally (much better), MyBatis should be able to map any result set to void
, which would mean that we can safely ignore the entire result set.
Actual result
Cannot use void
as a result for Postgres functions which return void
.
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (2 by maintainers)
If the change is small, maybe it’s worth doing. If it requires a lot of work, you could just close this issue - I agree that the workarounds are good enough. Though, maybe it’s worth adding a few lines to document this, because the error is quite strange.
Completely agreed. Unfortunately, that how the Postgres team designed stuff, and their JDBC driver works fine.
Thanks for the workarounds. I think the least weird for now is the one I had above: use
java.lang.Void
as the result type.