Spring boot 为什么Mybatis不能正确映射一个简单的枚举?

Spring boot 为什么Mybatis不能正确映射一个简单的枚举?,spring-boot,mybatis,spring-mybatis,Spring Boot,Mybatis,Spring Mybatis,据我所知,我没有做任何不寻常的事情。我有一个使用mybatis的spring boot应用程序: 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.conf

据我所知,我没有做任何不寻常的事情。我有一个使用mybatis的spring boot应用程序:

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
我的数据库表如下所示:

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 * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(@Param("workspaceId") final UUID workspaceId);
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;
}
只需一个这样的条目:

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 * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(@Param("workspaceId") final UUID workspaceId);
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;
}
在我的mapper文件中,我选择了所有引用,如下所示:

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 * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(@Param("workspaceId") final UUID workspaceId);
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映射器中使用和

@构造函数args{ @Argcolumn=site,javaType=Sites.class, @Argcolumn=workspace\u id,javaType=UUID.class, @Argcolumn=external\u id,javaType=String.class } @从工作空间\u外部\u引用中选择Select*,其中工作空间\u id={workspaceId} 列表findByWorkspace@ParamworkspaceId最终UUID工作空间ID; 其他列,即id、创建位置、更新位置将通过设置器自动映射(如果存在或反射)

或者,您也可以将默认的无参数构造函数添加到WorkspaceExternalReference类中。然后,所有列将在类实例化后自动映射


注意:要使其工作,需要为UUID注册一个类型处理程序,但您似乎已经这样做了,否则参数映射将无法工作

当没有默认构造函数时,在大多数情况下,需要让MyBatis知道哪些列要显式传递给构造函数

对于注释,它将如下所示。 您可以在XML映射器中使用和

@构造函数args{ @Argcolumn=site,javaType=Sites.class, @Argcolumn=workspace\u id,javaType=UUID.class, @Argcolumn=external\u id,javaType=String.class } @从工作空间\u外部\u引用中选择Select*,其中工作空间\u id={workspaceId} 列表findByWorkspace@ParamworkspaceId最终UUID工作空间ID; 其他列,即id、创建位置、更新位置将通过设置器自动映射(如果存在或反射)

或者,您也可以将默认的无参数构造函数添加到WorkspaceExternalReference类中。然后,所有列将在类实例化后自动映射


注意:要使其工作,需要为UUID注册一个类型处理程序,但您似乎已经这样做了,否则参数映射将无法工作

这是一个令人敬畏的答案。我不知道ConstructorArgs注释,谢谢。这当然是一个解决方案,作为改变,有人没有建议重新设计我的整个程序。我实现的另一个解决方案是确保没有Args构造函数,我们正在使用Lombok,因此它与添加@noargsconstuctor一样简单。如果你不介意把它添加到你的答案中,我很乐意接受你的答案。非常感谢,好主意。更新了答案:这是一个令人敬畏的答案。我不知道ConstructorArgs注释,谢谢。这当然是一个解决方案,作为改变,有人没有建议重新设计我的整个程序。我实现的另一个解决方案是确保没有Args构造函数,我们正在使用Lombok,因此它与添加@noargsconstuctor一样简单。如果你不介意把它添加到你的答案中,我很乐意接受你的答案。非常感谢,好主意。更新了答案: