1

My Environment:

  • Java 8
  • MyBatis 3.5.6
  • SAP jConnect for JDBC 16.0 SP04 (note: 16.0 SP04 is now JDBC4.2 compliant)

I have a problem on LocalDateTimeHandler with SAP jConnect. Executing a SELECT statement for a DATETIME column with mapping to a LocalDateTime property causes a SQLException (caused by ClassCastException).

Caused by: java.lang.ClassCastException: Cannot cast com.sybase.jdbc42.tds.SybTimestamp to java.time.LocalDateTime
    at java.lang.Class.cast(Class.java:3369)
    at com.sybase.jdbc42.jdbc.SybResultSet.convertObjectToJavaType(SybResultSet.java:3665)
    at com.sybase.jdbc42.jdbc.SybResultSet.getObject(SybResultSet.java:3632)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.ibatis.logging.jdbc.ResultSetLogger.invoke(ResultSetLogger.java:69)
    at com.sun.proxy.$Proxy211.getObject(Unknown Source)
    at org.apache.ibatis.type.LocalDateTimeTypeHandler.getNullableResult(LocalDateTimeTypeHandler.java:38)
    at org.apache.ibatis.type.LocalDateTimeTypeHandler.getNullableResult(LocalDateTimeTypeHandler.java:28)
    at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:85)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getPropertyMappingValue(DefaultResultSetHandler.java:511)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.applyPropertyMappings(DefaultResultSetHandler.java:480)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:404)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:354)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:328)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:301)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:194)
    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.ReuseExecutor.doQuery(ReuseExecutor.java:60)
    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.CachingExecutor.query(CachingExecutor.java:109)
    at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:89)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427)
    ... 54 more

The MyBatis LocalDateTimeTypeHandler expects ResultSet.getObject() to return a LocalDateTime object, but jConnect doesn't support it. According to the javadoc and JDBC 4.2 specification for the TIMESTAMP column, only java.sql.Timestamp type conversion must be supported at a minimum, but other type conversions (including LocalDateTime) are not expected to be supported by some vendors.

My Questions:

  • Is this a bug of MyBatis ? or by design to support only some specific vendors ?
  • Is there any workaround ?

Reference

murai
  • 11
  • 3
  • Are you sure you want to use [`TIMESTAMP`](https://stackoverflow.com/q/3500703/1261766)? Last time I checked, the built-in `LocalDateTimeTypeHandler` worked for a `DATETIME` column. – ave Aug 05 '21 at 05:28
  • Just to be clear, it is not a bug. JDBC 4.2 compliant drivers are expected to support `LocalDateTime` via `setObject()` and `getObject()`. See http://mail.openjdk.java.net/pipermail/jdbc-spec-discuss/2012-December/000010.html Besides, converting `LocalDateTime` to/from `java.sql.Timestamp` could generate [unexpected result](https://github.com/mybatis/mybatis-3/pull/1478#issuecomment-513266102) depending on the default time zone. In case your driver does not support the conversion, [here](https://github.com/mybatis/mybatis-3/pull/1478#issuecomment-512226734) is a workaround. – ave Aug 05 '21 at 14:41
  • @ave The database column type I'm using is actually `DATETIME`. (I'll correct the question later). Could you please let me know the SAP ASE version and edition in your environment which works for you ? I will check my env if there are something wrong. – murai Aug 06 '21 at 08:54
  • Sorry, I got confused, it seems. I re-tested using jconn4.jar bundled with SAP ASE 16 SP03 and the driver does not support `LocalDateTime` indeed. You should report the issue to SAP. Until they fix it, you may have to use the workaround I mentioned. The old implementations may work fine if your system runs on a time zone that does not have DST. – ave Aug 06 '21 at 18:15
  • @ave Thank you for the info. Just for your information, jconn4.jar is a JDBC4.0 compliant implementation. The jconn4.jar has the `ResultSet.getObject()` but as an abstract method so that `LocalDateTimeTypeHandler` cannot call it. The jconn42.jar is a JDBC4.2 compliant provided by ASE 16 SP04. – murai Aug 08 '21 at 02:04
  • Here are some more details https://github.com/mybatis/mybatis-3/issues/1644 – wittich Jan 20 '22 at 00:15

0 Answers0