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语句对保留字的语法检查更严格,因此报错。
解决办法
- 给表名添加反引号:修改实体类的
@Table注解,用反引号包裹表名,让Hibernate生成的SQL自动带上反引号,避免保留字冲突:
@Table(name = "`USER`")
- 修改表名为非保留字:直接把表名改成
USERS这类非保留字,从根源上避免问题。
内容的提问来源于stack exchange,提问作者Oirampok
相关产品推荐
相关产品推荐

