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

Spring JPA原生save方法无法保存含MySQL JSON列的实体

问题:JPA save方法保存含JSON字段的实体报错,自定义原生查询却能正常执行?

定义的User实体类(DETAILS为MySQL JSON类型)

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "USER")
public class User implements Serializable {

    @Id
    @Column(name = "NAME", nullable = false)
    private String name;

    @Column(name = "AGE", nullable = false)
    private int age;

    @Column(name = "DETAILS", nullable = false, columnDefinition = "json" )
    private String details;
}

要持久化的用户对象

{
    "age": 5,
    "name": "MARIO",
    "details": "{\"country\":\"Indonesia\"}"
}

使用JpaRepository的save方法报错信息

java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'age=5 where name='MARIO'' at line 1

自定义原生查询的Repository方法(可正常保存)

@Repository
public interface UserRepository extends JpaRepository<User, String> {

    @Modifying
    @Transactional
    @Query(value = "insert into USER (NAME, AGE, DETAILS) values (:name, :age, :details)", nativeQuery = true)
    void saveWithJson(String name, String details, int age);
}

疑问:为什么JPA自带的save方法报错,自定义原生查询却能正常保存?原以为两者底层逻辑一致。


原因分析与解决办法

核心原因:表名USER是MySQL保留关键字

JPA的save方法并非直接执行INSERT,它会先根据ID字段(这里是name)执行SELECT语句检查记录是否存在:

  • 若判断记录不存在,执行INSERT;
  • 若判断记录已存在,执行UPDATE。

报错信息指向UPDATE语句的语法错误,说明JPA认为该记录已存在,生成的UPDATE SQL类似:

update USER set age=5 where name='MARIO'

MySQL中USER是保留关键字,直接用作表名会触发语法错误。而自定义的原生查询是显式执行INSERT,MySQL在某些SQL模式下对INSERT中的保留字检查较宽松,所以能成功执行,但UPDATE语句对保留字的语法检查更严格,因此报错。

解决办法

  1. 给表名添加反引号:修改实体类的@Table注解,用反引号包裹表名,让Hibernate生成的SQL自动带上反引号,避免保留字冲突:
@Table(name = "`USER`")
  1. 修改表名为非保留字:直接把表名改成USERS这类非保留字,从根源上避免问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:45:32