[英]Mybatis not handling ZonedDateTime
I have columns in a database table of type DATE
which I'd like mybatis to convert to java.time.ZonedDateTime
but it seems that the built in ZonedDateTimeHandler is not working.我在DATE
类型的数据库表中有列,我希望 mybatis 将其转换为java.time.ZonedDateTime
但似乎内置的ZonedDateTimeHandler不起作用。 I get the following exception我得到以下异常
Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'UPDATED_DATE' from result set. Cause: java.sql.SQLSyntaxErrorException: incompatible data type in conversion
at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:87)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createUsingConstructor(DefaultResultSetHandler.java:711)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createByConstructorSignature(DefaultResultSetHandler.java:694)
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.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:151)
... 36 common frames omitted
Caused by: java.sql.SQLSyntaxErrorException: incompatible data type in conversion
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCResultSet.getObject(Unknown Source)
at org.hsqldb.jdbc.JDBCResultSet.getObject(Unknown Source)
at com.zaxxer.hikari.pool.HikariProxyResultSet.getObject(HikariProxyResultSet.java)
at org.apache.ibatis.type.ZonedDateTimeTypeHandler.getNullableResult(ZonedDateTimeTypeHandler.java:38)
at org.apache.ibatis.type.ZonedDateTimeTypeHandler.getNullableResult(ZonedDateTimeTypeHandler.java:28)
at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:85)
... 53 common frames omitted
Caused by: org.hsqldb.HsqlException: incompatible data type in conversion
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.error.Error.error(Unknown Source)
... 60 common frames omitted
It turned out that the default ZonedDateTimeTypeHandler assumes that the jdbc driver knows how to handle ZonedDateTime
which is NOT the case with hsqldb or oracle事实证明,默认的ZonedDateTimeTypeHandler假定 jdbc 驱动程序知道如何处理ZonedDateTime
,而 hsqldb 或 oracle 并非如此
public class ZonedDateTimeTypeHandler extends BaseTypeHandler<ZonedDateTime> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, ZonedDateTime parameter, JdbcType jdbcType) throws SQLException {
ps.setObject(i, parameter);
}
@Override
public ZonedDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getObject(columnName, ZonedDateTime.class);
}
...
}
I fixed this with a custom handler that uses setTimestamp(...)
and getTimestamp(...)
under the hood我用一个自定义处理程序修复了这个问题,该处理程序在后台使用setTimestamp(...)
和getTimestamp(...)
@AllArgsConstructor
public class ZonedDateTimeTypeHandler extends BaseTypeHandler<ZonedDateTime> {
private final ZoneId zoneId;
@Override
public void setNonNullParameter(PreparedStatement ps, int i, ZonedDateTime parameter, JdbcType jdbcType) throws SQLException {
ps.setTimestamp(i, Timestamp.from(parameter.toInstant()));
}
@Override
public ZonedDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
Timestamp ts = rs.getTimestamp(columnName);
return ts == null ? null : ts.toInstant().atZone(zoneId);
}
@Override
public ZonedDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
Timestamp ts = rs.getTimestamp(columnIndex);
return ts == null ? null : ts.toInstant().atZone(zoneId);
}
@Override
public ZonedDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
Timestamp ts = cs.getTimestamp(columnIndex);
return ts == null ? null : ts.toInstant().atZone(zoneId);
}
}
Which I registered using the following code我使用以下代码注册
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) {
ZoneId zoneId = ZoneId.of("UTC");
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("default", transactionFactory, dataSource);
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(environment);
configuration.getTypeHandlerRegistry().register(ZonedDateTime.class, new ZonedDateTimeTypeHandler(zoneId));
configuration.addMapper(MyMapper.class);
return new SqlSessionFactoryBuilder().build(configuration);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.