You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebFlux与R2DBC:枚举存MySQL TinyInt及序列化字符串异常解决

解决Spring WebFlux + R2DBC枚举字段tinyint存储与JSON字符串返回问题

问题分析

插入报错的核心原因是:R2DBC默认将枚举的名称字符串(如PENDING)传递给MySQL的tinyint字段,类型不匹配导致数据库抛出异常。需要同时处理两个关键环节:

  • R2DBC与数据库交互时:实现枚举 ↔ tinyint 的双向类型转换
  • API返回JSON时:将枚举序列化为对应的名称字符串

解决方案

1. 自定义R2DBC枚举转换器

通过实现读写转换器,让R2DBC正确处理枚举与tinyint的映射逻辑:

写入转换器(枚举转tinyint)

负责将枚举对象转换为数据库需要的整数类型:

import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.WritingConverter;

@WritingConverter
public enum StatusEnumWriteConverter implements Converter<StatusEnum, Integer> {
    INSTANCE;

    @Override
    public Integer convert(StatusEnum source) {
        return source.value;
    }
}

读取转换器(tinyint转枚举)

负责将数据库返回的整数转换为对应的枚举实例:

import io.r2dbc.spi.Row;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;

@ReadingConverter
public enum StatusEnumReadConverter implements Converter<Row, StatusEnum> {
    INSTANCE;

    @Override
    public StatusEnum convert(Row source) {
        Integer statusValue = source.get("status", Integer.class);
        for (StatusEnum status : StatusEnum.values()) {
            if (status.value == statusValue) {
                return status;
            }
        }
        return StatusEnum.UNKNOWN; // 匹配不到时返回默认枚举值
    }
}

注册转换器到R2DBC配置

将自定义转换器注入R2DBC的转换体系:

import org.springframework.context.annotation.Configuration;
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
import org.springframework.data.r2dbc.convert.R2dbcCustomConversions;

import java.util.Arrays;

@Configuration
public class R2dbcConfig extends AbstractR2dbcConfiguration {

    // 若需自定义数据库连接工厂,可重写connectionFactory方法(根据自身数据源配置调整)

    @Override
    protected R2dbcCustomConversions r2dbcCustomConversions() {
        return new R2dbcCustomConversions(
                Arrays.asList(
                        StatusEnumWriteConverter.INSTANCE,
                        StatusEnumReadConverter.INSTANCE
                )
        );
    }
}

2. 配置Jackson序列化枚举为字符串名称

有两种方式实现API返回时枚举序列化为名称字符串:

方式一:枚举类添加@JsonValue注解(推荐)

直接在枚举中定义序列化时返回的名称,同时支持前端传入字符串反序列化为枚举:

import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;

@AllArgsConstructor
public enum StatusEnum {
    PENDING(11),
    IN_PROGRESS(12),
    SUCCESSFUL(13),
    FAILED(14),
    UNKNOWN(255);

    final int value;

    @JsonValue
    public String getStatusName() {
        return this.name();
    }
}

方式二:全局WebFlux Jackson配置

若需全局统一处理枚举序列化逻辑,可配置WebFlux的JSON编解码器:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.EnumSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.web.reactive.config.WebFluxConfigurer;

@Configuration
public class WebFluxConfig implements WebFluxConfigurer {

    @Bean
    public Jackson2JsonEncoder jackson2JsonEncoder() {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(StatusEnum.class, new EnumSerializer(EnumSerializer.Feature.WRITE_ENUMS_USING_NAME));
        mapper.registerModule(module);
        return new Jackson2JsonEncoder(mapper);
    }

    @Bean
    public Jackson2JsonDecoder jackson2JsonDecoder() {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(StatusEnum.class, new EnumSerializer(EnumSerializer.Feature.WRITE_ENUMS_USING_NAME));
        mapper.registerModule(module);
        return new Jackson2JsonDecoder(mapper);
    }
}

验证效果

  • 插入数据:R2DBC会自动将StatusEnum.PENDING转换为11存入tinyint字段
  • 查询数据:数据库返回的tinyint值会转换为对应的枚举实例
  • API返回:枚举会序列化为名称字符串,完全符合期望格式:
[
    { "id": 1, "status": "PENDING" },
    { "id": 2, "status": "IN_PROGRESS" },
    { "id": 3, "status": "SUCCESSFUL" },
    { "id": 4, "status": "FAILED" }
]

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:16:17