将转换后的枚举值插入MySql Smallint列时的JDBC java.sql.SQLException

问题描述

我正在尝试使用一个枚举来显示“权限”字段(读取,写入等)的人类可读值。当我将记录存储在关联的MysqL表中时,权限枚举字段需要转换为关联的整数(1、2、4等)。但是,当我运行SpringBoot应用程序并调用POST端点时,却遇到了一个奇怪的sql异常。例外:

无法执行DbAction.InsertRoot(entity = Invite(id = null,createdAt = 2020-09-19 18:12:01,createdBy = 1,listId = 8,token = c3b95dc9-ec4d-4dde- a461-b12746afa61e,expiresAt = 2020-09-26 18:12:01,权限= 2),generatedId = null)],其根本原因是 java.sql.sqlException:错误的整数值:第1行的“ permission”列的“ WRITE” 在com.MysqL.cj.jdbc.exceptions.sqlError.createsqlException(sqlError.java:129)〜[mysql-connector-java-8.0.19.jar:8.0.19]

令我感到奇怪的是,db操作将报告要插入的“ permission”字段为2,但是sql异常报告“ WRITE”不是有效的整数值。知道我可能会缺少什么吗?

这是值得注意的代码和配置。请注意,我使用的是JDBC,而不是JPA:

这是枚举类:

public enum Permission {
    READ(1),WRITE(2),CREATE(4),DELETE(8),ADMIN(16);

    private Integer value;

    Permission(final Integer value) {
        this.value = value;
    }

    public Integer getValue() {
        return this.value;
    }

    //@JsonCreator
    @Override
    public String toString() {
        return this.getValue().toString();
    }

    //@JsonValue
    public static Permission forValue(final String name) {
        return Permission.valueOf(name);
    }
}

以下是POJO /实体:

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.Id;

@Data
@AllArgsConstructor
@Builder
@ToString
public class Invite {

    public static final int TOKEN_MINIMUM_LENGTH = 36;
    public static final int TOKEN_MAXIMUM_LENGTH = 40;

    @Id
    private Long id;

    private String createdAt;

    private String createdBy;

    private Long listId;

    private String token;

    private String expiresAt;

    private Permission permission;

}

这是JdbcCustomConversions。应该注意的是,在调试时,ReadingConverter似乎已跳闸,但WritingConverter却没有。我不确定这是否是问题的一部分。


import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration;
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
import java.util.Arrays;

@Configuration
@EnableAutoConfiguration
public class JdbcConfiguration extends AbstractJdbcConfiguration {

    /**
     * JDBC Custom Conversions.
     *
     */
    @Override
    public JdbcCustomConversions jdbcCustomConversions() {
        return new JdbcCustomConversions(Arrays.asList(PermissionToInteger.INSTANCE,IntegerToPermission.INSTANCE));
    }

    // I have never seen this get tripped
    @WritingConverter
    enum PermissionToInteger implements Converter<Permission,Integer> {

        INSTANCE;

        @Override
        public Integer convert(final Permission permission) {
            return permission == null ? null : permission.getValue();
        }
    }

    // this one trips in the debugger and appears to be working fine
    @ReadingConverter
    enum IntegerToPermission implements Converter<Integer,Permission> {

        INSTANCE;

        @Override
        public Permission convert(final Integer code) {
            for (final Permission perm: Permission.values()) {
                if (perm.getValue().equals(code)) {
                    return perm;
                }
            }
            return null;
        }
    }
}

这是简单的存储库:

import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
import java.util.Optional;

public interface InviteRepository extends CrudRepository<Invite,Long> {

    @Query("SELECT * from invite where token = :token")
    Optional<Invite> findByToken(String token);

    @Query("SELECT * from invite where created_by = :userId")
    List<Invite> findByUserId(Long userId);

    @Query("SELECT * from invite where list_id = :wishlistId")
    List<Invite> findByWishlistId(Long wishlistId);

}

任何提示将不胜感激!

亚伦

解决方法

解决方法是将WritingConverter更改为String而不是Integer:

@WritingConverter
public enum PermissionToInteger implements Converter<Permission,String> {

    INSTANCE;

    @Override
    public String convert(final Permission permission) {
        return permission == null ? null : permission.getValue().toString();
    }
}
,

spring jdbc 的一些调试源码后,可以通过目标类从 JdbcValue 类赋值,将 enum 类型转换为整数。

   @Bean
   override fun jdbcCustomConversions() = JdbcCustomConversions(arrayListOf(
        @WritingConverter
        object: Converter<LoginTypes,JdbcValue> {
            override fun convert(p0: LoginTypes) = JdbcValue.of(p0.code,JDBCType.INTEGER)
        },@ReadingConverter
        object:Converter<Int,LoginTypes>{
            override fun convert(p0: Int): LoginTypes? = LoginTypes.values().first { it.code==p0 }
        }```