使用JPA和Hibernate 6向Spanner插入JSON数据报错求助
问题:使用JPA+Hibernate 6向Spanner JSON列插入数据时类型不匹配
插入数据时触发如下错误:
Error:
Value has type STRING which cannot be inserted into column json_data, which has type JSON
已参考相关Spanner JPA集成资料但未解决问题,附上代码及配置详情,求解决建议:
实体类
import com.google.cloud.spanner.hibernate.PooledBitReversedSequenceStyleGenerator; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.id.enhanced.SequenceStyleGenerator; import org.hibernate.type.SqlTypes; import java.util.Map; @AllArgsConstructor @NoArgsConstructor @Entity @Table(name = "demo") public class Demo { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence_generator") @GenericGenerator( name = "sequence_generator", strategy = "com.google.cloud.spanner.hibernate.PooledBitReversedSequenceStyleGenerator", parameters = { @org.hibernate.annotations.Parameter(name = SequenceStyleGenerator.SEQUENCE_PARAM, value = "demo_sequence"), @org.hibernate.annotations.Parameter(name = SequenceStyleGenerator.INCREMENT_PARAM, value = "200"), @org.hibernate.annotations.Parameter(name = SequenceStyleGenerator.INITIAL_PARAM, value = "50000"), @org.hibernate.annotations.Parameter(name = PooledBitReversedSequenceStyleGenerator.EXCLUDE_RANGE_PARAM, value = "[1,1000]"), }) private Long id; @JdbcTypeCode(SqlTypes.JSON) private Map<String, Object> jsonData; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Map<String, Object> getJsonData() { return jsonData; } public void setJsonData(Map<String, Object> jsonData) { this.jsonData = jsonData; } }
DDL和DML语句
drop table IF EXISTS demo; drop sequence IF EXISTS demo_sequence; CREATE SEQUENCE demo_sequence OPTIONS ( sequence_kind="bit_reversed_positive" ); create table demo( id INT64 NOT NULL default (GET_NEXT_SEQUENCE_VALUE(SEQUENCE demo_sequence)), json_data JSON, ) PRIMARY key(id); insert into demo(json_data) values (JSON '{"name":"tom","age":30}');
POM依赖配置
<properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.google.cloud</groupId> <artifactId>google-cloud-spanner-hibernate-dialect</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>com.google.cloud</groupId> <artifactId>google-cloud-spanner</artifactId> <version>6.80.1</version> </dependency> <dependency> <groupId>com.google.cloud</groupId> <artifactId>spring-cloud-gcp-data-spanner</artifactId> <version>5.8.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> <version>3.3.5</version> </dependency> <dependency> <groupId>com.google.cloud</groupId> <artifactId>google-cloud-spanner-jdbc</artifactId> <version>2.24.1</version> </dependency> <dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-60</artifactId> <version>2.21.1</version> </dependency> </dependencies>
解决建议
1. 增强JSON字段的类型注解
仅使用@JdbcTypeCode(SqlTypes.JSON)可能无法被Spanner方言正确识别,结合hibernate-types的@Type注解明确指定JSON类型处理器:
import com.vladmihalcea.hibernate.type.json.JsonType; // ... @Type(JsonType.class) @JdbcTypeCode(SqlTypes.JSON) private Map<String, Object> jsonData;
2. 对齐依赖版本兼容性
google-cloud-spanner-hibernate-dialect与google-cloud-spanner-jdbc版本需匹配,当前方言版本3.3.0建议搭配对应版本的JDBC驱动,避免版本不兼容导致的类型转换错误。
3. 配置Hibernate全局JSON类型映射
在application.properties中添加以下配置,强制Hibernate使用Spanner兼容的JSON类型处理逻辑:
spring.jpa.properties.hibernate.type.preferred_json_jdbc_type=JSON spring.jpa.properties.hibernate.dialect=com.google.cloud.spanner.hibernate.SpannerDialect
4. 移除冲突依赖
当前依赖中同时引入了spring-cloud-gcp-data-spanner和JPA相关依赖,二者可能存在类型处理逻辑冲突。如果使用JPA+Hibernate方案,建议移除spring-cloud-gcp-data-spanner依赖。
5. 验证SQL生成逻辑
开启Hibernate SQL日志,查看插入语句的参数绑定情况:
spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true
若日志显示插入的是字符串而非JSON字面量,说明类型转换未生效,需进一步调整注解或配置。
内容的提问来源于stack exchange,提问作者Suga Raj
相关产品推荐
相关产品推荐

