问题描述
我想在 sql Server 中定义列,以便 Mybatis Generator 生成 java.time.Instant
或 java.time.OffsetDateTime
。根据 Mybatis Generator Core,当 TIMESTAMP_WITH_TIMEZONE
为 OffsetDateTime
usejsr310Types
类型的列映射到 true
我在 DDL 中使用了类型 DATETIMEOFFSET
,但我的实体被翻译为 Object
。当然,使用 DATETIME2
会导致 LocalDateTime
,这不是我想要的。
示例 DDL
CREATE TABLE Users
(
UserId Int IDENTITY (1,1) NOT NULL,UserFirstName Nvarchar(50) NOT NULL,UserLastName Nvarchar(50) NOT NULL,UserEmail Nvarchar(100) NOT NULL,Created DATETIME2 NOT NULL,Creator INT NOT NULL,Modified DATETIME2 NOT NULL,Modifier INT NOT NULL
);
generatorConfig.xml
的相关片段
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"https://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<contexttargetRuntime="MyBatis3Dynamicsql" defaultModelType="hierarchical">
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="${jdbcDriverClass}"
connectionURL="${jdbcUrl}"
userId="${jdbcUsername}"
password="${jdbcPassword}"
>
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<javaTypeResolver type="org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl">
<property name="usejsr310Types" value="true"/>
</javaTypeResolver>
<javaModelGenerator targetPackage=""
targetProject="${workingDir}/src/main/java"/>
<javaClientGenerator targetPackage=""
targetProject="${workingDir}/src/main/java" type="ANNOTATEDMAPPER"/>
<table tableName="Users" domainObjectName="User" mapperName="UserBaseMapper">
<property name="rootInterface" value=""/>
<generatedKey column="UserId" identity="true" sqlStatement="JDBC"/>
</table>
</context>
</generatorConfiguration>
解决方法
MyBatis Generator 依赖于 JDBC 驱动程序进行类型解析。您可以在此处查看 SQL Server 如何进行类型映射:https://docs.microsoft.com/en-us/sql/connect/jdbc/using-basic-data-types?view=sql-server-ver15
根据该页面,DATETIMEOFFSET
映射到非标准 JDBC 类型 microsoft.sql.Types.DATETIMEOFFSET
。生成器对这种类型一无所知(MyBatis 本身也不知道)。这就是生成器将列解析为 Object
的原因。
如果您想在 SQL Server 中使用 DATETIMEOFFSET
列,那么您可以在生成器中使用覆盖将 Java 类型映射到 microsoft.sql.DateTimeOffset
。您还需要编写一个类型处理程序,以便 MyBatis 可以使用该类型。
不幸的是,SQL Server 似乎没有直接映射到 TIMESTAMP_WITH_TIMEZONE
的类型。
还有另一种方式。
建议 Mybatis 使用 Instant
<table tableName="Users" domainObjectName="User" mapperName="UserBaseMapper">
<property name="rootInterface" value=""/>
<generatedKey column="UserId" identity="true" sqlStatement="JDBC"/>
<columnOverride column="Created" jdbcType="TIMESTAMP_WITH_TIMEZONE" javaType="java.time.Instant"/>
<columnOverride column="Modified" jdbcType="TIMESTAMP_WITH_TIMEZONE" javaType="java.time.Instant"/>
</table>
也许(也许)JDBC 类型是多余的,但它该死的适用于 SQL Server 和 H2 DB,其中 H2 使用 TIMESTAMP WITH TIME ZONE
作为列类型