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

Spring Boot数据库JSON保存及查询报错问题求助

问题分析与解决方案

现有代码与环境

实体类

@Table("EXPERIMENTS")
data class Experiment(
    @Id val id: Long,
    val userId: Long,
    val time: String,
    @JsonProperty
    val data: Any
)

控制器接口

@PostMapping("/experiment")
fun saveUserExperiment(@RequestBody experiment: Experiment) = service.saveExperiment(experiment)

服务层

@Service
class ExperimentService(val db: ExperimentRepository) {
    fun saveExperiment(experiment: Experiment) = db.save(experiment)
    // ... 其他代码
}

仓库查询方法

@Query("select * from experiments")
fun getExperiments(): List<Experiment>

数据库表结构

experiments: table
    + columns
        id: int NN auto_increment = 1
        user_id: mediumtext NN
        time: timestamp default CURRENT_TIMESTAMP
        data: json
    + keys
        #1: PK (id) (underlying index PRIMARY)

核心问题与解决步骤

1. 修复查询时的空参数错误

错误Parameter specified as non-null is null的根源是:

  • 实体类中data: Any被声明为非空,但数据库data字段允许为空
  • JPA无法将JSON类型正确映射到无约束的Any类型

修改实体类:改用可空的Map<String, Any?>类型配合JSON映射注解,替代Any:

import org.hibernate.annotations.JdbcTypeCode
import java.sql.Types
import jakarta.persistence.Column

@Table("EXPERIMENTS")
data class Experiment(
    @Id val id: Long,
    val userId: Long,
    val time: String,
    @JdbcTypeCode(Types.JSON) // 明确映射JSON类型(Spring Boot 2.2+ 适用)
    @Column(columnDefinition = "json") // 兼容数据库JSON字段定义
    val data: Map<String, Any?>? // 改为可空类型,适配数据库字段
)

2. 消除保存时的反射警告

警告源于Spring反射访问LinkedHashMap内部字段,原因是用Any接收JSON数据导致Jackson解析后无法正常处理。改用Map<String, Any?>后,Jackson会直接解析为标准LinkedHashMap,无需非法反射操作,警告自动消失。

若仍有警告,可升级Spring Core版本至5.3.10+,该版本修复了相关反射兼容问题。

3. 关于API返回200但JSON字段为空的疑问

从你提供的Postman响应来看,返回的data字段是正常的:

{"id":7,"userId":1,"time":"2018-10-18 05:30:57.907","data":{"red":123,"blue":123,"green":123}}

若实际场景出现data为空的情况,排查方向:

  • 检查数据库data字段是否真的存储了值
  • 确认实体类的JSON映射注解配置正确
  • 检查Jackson序列化配置:若application.properties中有spring.jackson.default-property-inclusion=non_null,当data为null时不会显示在返回结果中,属于正常行为

4. 优化仓库查询方法

无需使用原生SQL,直接用Spring Data JPA默认查询方法即可:

interface ExperimentRepository : JpaRepository<Experiment, Long> {
    // 替代自定义@Query,自动生成正确的查询语句
    override fun findAll(): List<Experiment>
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:24:20