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

如何让jsonb ColumnTransformer兼容H2数据库以实现测试切换

PostgreSQL jsonb 兼容H2数据库测试方案

问题背景

后端基于PostgreSQL数据库开发,实体类通过jsonb类型存储Map结构数据,搭配@ColumnTransformer实现写入转换逻辑,但在H2数据库执行测试时,触发Unknown data type: "JSONB"报错。

实体类代码

@JsonProperty("home_address")
@Column(name = "home_address", nullable = true, columnDefinition = "jsonb")
@ColumnTransformer(write = "?::jsonb")
@Convert(converter = JsonbConverter.class)
private Map<String, Object> homeAddress;

报错信息

address jsonb,

)" via JDBC [Unknown data type: "JSONB";]
    at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:94)
    at org.hibernate.tool.schema.internal.Helper.applySqlString(Helper.java:233)
    at org.hibernate.tool.schema.internal.Helper.applySqlStrings(Helper.java:217)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createTables(SchemaCreatorImpl.java:428)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createSequencesTablesConstraints(SchemaCreatorImpl.java:344)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata(SchemaCreatorImpl.java:239)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation(SchemaCreatorImpl.java:172)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:142)
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:118)
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:250)
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:144)
    at java.base/java.util.HashMap.forEach(HashMap.java:1429)

解决方案

1. 配置H2为PostgreSQL兼容模式

修改H2数据库连接URL,添加兼容参数,让H2模拟PostgreSQL的类型解析逻辑:

spring.datasource.url=jdbc:h2:mem:testdb;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE;DB_CLOSE_DELAY=-1

添加MODE=PostgreSQL后,H2会自动将jsonb识别为JSON类型的别名,直接解决类型未知报错。

2. 优化实体类注解适配双数据库

方案A:使用Hibernate Types库自动适配

引入hibernate-types依赖(根据Hibernate版本选择对应artifactId,如Hibernate 5.x用hibernate-types-52),修改实体类注解:

@JsonProperty("home_address")
@Column(name = "home_address", nullable = true)
@Type(type = "com.vladmihalcea.hibernate.type.json.JsonBinaryType")
private Map<String, Object> homeAddress;

该类型处理器会自动适配数据库:PostgreSQL环境用jsonb,H2环境用原生JSON类型,无需手动配置columnDefinition和ColumnTransformer。

方案B:条件化配置注解(无额外依赖)

通过Spring Profile区分测试与生产环境,实现注解动态切换:

  • 生产环境(PostgreSQL)保留原注解;
  • 测试环境(H2)替换类型定义与转换逻辑:
@JsonProperty("home_address")
@Column(name = "home_address", nullable = true, 
        columnDefinition = "${db.json.type:jsonb}")
@ColumnTransformer(write = "${db.json.transform:?::jsonb}")
@Convert(converter = JsonbConverter.class)
private Map<String, Object> homeAddress;

测试配置文件中添加参数:

db.json.type=json
db.json.transform=CAST(? AS JSON)

3. 初始化H2时注册jsonb类型

若不想修改连接URL或实体类,可在H2初始化阶段执行SQL注册jsonb类型:
创建初始化脚本src/test/resources/h2-init.sql:

CREATE TYPE JSONB AS JSON;

测试配置中指定脚本位置:

spring.sql.init.data-locations=classpath:h2-init.sql

验证

启动测试后,检查H2数据库表结构是否正常创建,同时验证JSON数据的读写逻辑,确保在PostgreSQL和H2环境中都能正确序列化、反序列化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:25:08