为什么 Mybatis 不能正确映射一个简单的 ENUM?
Why doesn't Mybatis map a simple ENUM correctly?
据我所知,我没有做任何不寻常的事情。我有一个使用 mybatis 的 spring 启动应用程序:
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1'
我有一个非常简单的 mybatis 配置 application.properties:
## MyBatis ##
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-statement-timeout=30
我的数据库 table 如下所示:
CREATE TABLE workspace_external_references (
id CHAR(36) PRIMARY KEY,
workspace_id CHAR(36) NOT NULL,
site VARCHAR(255) NOT NULL,
external_id VARCHAR(255) NOT NULL,
created_at DATETIME(6) NOT NULL DEFAULT NOW(6),
updated_at DATETIME(6) NOT NULL DEFAULT NOW(6),
FOREIGN KEY (workspace_id) REFERENCES workspaces (id) ON DELETE CASCADE
)
只有一个这样的条目:
'a907c0af-216a-41e0-b16d-42107a7af05f', 'e99e4ab4-839e-405a-982b-08e00fbfb2d4', 'ABC', '6', '2020-06-09 00:19:20.135822', '2020-06-09 00:19:20.135822'
在我的映射器文件中,我正在对所有引用进行 select,如下所示:
@Select("SELECT * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(@Param("workspaceId") final UUID workspaceId);
而应该映射到的 java 对象如下所示:
public class WorkspaceExternalReference {
private UUID id;
private UUID workspaceId;
private Sites site;
private String externalId;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public WorkspaceExternalReference(
final Sites site,
final UUID workspaceId,
final String externalId) {
this.site = site;
this.workspaceId = workspaceId;
this.externalId = externalId;
}
}
public enum Sites {
ABC, XYZ;
}
为什么这不起作用? 我收到了这个错误:
Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'id' from result set. Cause: java.lang.IllegalArgumentException: No enum constant com.acme.Sites.a907c0af-216a-41e0-b16d-42107a7af05f
当没有默认构造函数时,你需要让 MyBatis 明确地知道哪些列要传递给构造函数(大多数情况下)。
有了注释,它看起来如下。
您可以在 XML 映射器中使用 <resultMap>
和 <constructor>
。
@ConstructorArgs({
@Arg(column = "site", javaType = Sites.class),
@Arg(column = "workspace_id", javaType = UUID.class),
@Arg(column = "external_id", javaType = String.class)
})
@Select("SELECT * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(@Param("workspaceId") final UUID workspaceId);
其他列(即 id
、created_at
、updated_at
)将通过设置器(如果有)或反射自动映射。
或者,您可以将默认(无参数)构造函数添加到 WorkspaceExternalReference
class。然后在 class 实例化后所有列将被自动映射。
注意:要使其工作,需要为 UUID
注册一个类型处理程序,但您似乎已经完成了(否则参数映射将无法工作)。
据我所知,我没有做任何不寻常的事情。我有一个使用 mybatis 的 spring 启动应用程序:
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1'
我有一个非常简单的 mybatis 配置 application.properties:
## MyBatis ##
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-statement-timeout=30
我的数据库 table 如下所示:
CREATE TABLE workspace_external_references (
id CHAR(36) PRIMARY KEY,
workspace_id CHAR(36) NOT NULL,
site VARCHAR(255) NOT NULL,
external_id VARCHAR(255) NOT NULL,
created_at DATETIME(6) NOT NULL DEFAULT NOW(6),
updated_at DATETIME(6) NOT NULL DEFAULT NOW(6),
FOREIGN KEY (workspace_id) REFERENCES workspaces (id) ON DELETE CASCADE
)
只有一个这样的条目:
'a907c0af-216a-41e0-b16d-42107a7af05f', 'e99e4ab4-839e-405a-982b-08e00fbfb2d4', 'ABC', '6', '2020-06-09 00:19:20.135822', '2020-06-09 00:19:20.135822'
在我的映射器文件中,我正在对所有引用进行 select,如下所示:
@Select("SELECT * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(@Param("workspaceId") final UUID workspaceId);
而应该映射到的 java 对象如下所示:
public class WorkspaceExternalReference {
private UUID id;
private UUID workspaceId;
private Sites site;
private String externalId;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public WorkspaceExternalReference(
final Sites site,
final UUID workspaceId,
final String externalId) {
this.site = site;
this.workspaceId = workspaceId;
this.externalId = externalId;
}
}
public enum Sites {
ABC, XYZ;
}
为什么这不起作用? 我收到了这个错误:
Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'id' from result set. Cause: java.lang.IllegalArgumentException: No enum constant com.acme.Sites.a907c0af-216a-41e0-b16d-42107a7af05f
当没有默认构造函数时,你需要让 MyBatis 明确地知道哪些列要传递给构造函数(大多数情况下)。
有了注释,它看起来如下。
您可以在 XML 映射器中使用 <resultMap>
和 <constructor>
。
@ConstructorArgs({
@Arg(column = "site", javaType = Sites.class),
@Arg(column = "workspace_id", javaType = UUID.class),
@Arg(column = "external_id", javaType = String.class)
})
@Select("SELECT * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(@Param("workspaceId") final UUID workspaceId);
其他列(即 id
、created_at
、updated_at
)将通过设置器(如果有)或反射自动映射。
或者,您可以将默认(无参数)构造函数添加到 WorkspaceExternalReference
class。然后在 class 实例化后所有列将被自动映射。
注意:要使其工作,需要为 UUID
注册一个类型处理程序,但您似乎已经完成了(否则参数映射将无法工作)。