为何PostgreSQL执行SELECT *返回JSONB,显式查data返回PGobject?
问题分析与解答
为什么会出现类型差异?
核心原因是jOOQ获取列元数据的方式不同:
- 用
asterisk()(也就是select *)查询时,jOOQ会从PostgreSQL系统表拉取完整的表结构元数据,明确知道data列是JSONB类型,所以会自动用对应的JSONB绑定器解析结果,最终返回jOOQ封装的JSONB类型对象。 - 显式指定
field(DATA_COLUMN)时,因为没有用代码生成工具生成表结构类,jOOQ没法从预定义的元数据里知道这个列的具体类型,只能把它当作通用Object处理。这时PostgreSQL的JDBC驱动会直接返回原生的PGobject(这是驱动对PostgreSQL特定类型的通用封装),jOOQ不会自动做类型转换。
说白了就是:select *能拿到完整的列类型信息,手动指定字段时jOOQ缺类型上下文,只能用JDBC驱动的原生返回。
能不能稳定依赖某一种类型?
可以,只要固定你的查询写法就行:
要稳定拿到JSONB类型
有两种靠谱的方式:
- 一直用
select *查询,确保jOOQ能获取完整表元数据来做类型转换。 - 显式指定字段时,给
field()方法加上类型参数,明确告诉jOOQ列的类型:
这样jOOQ就知道要把select( field(ID_COLUMN, String.class), field(DATA_COLUMN, JSONB.class) ).from(DSL.table("test_table")) .where(field(ID_COLUMN).eq(id)) .fetch().intoMaps();data列解析成JSONB类型,不会返回PGobject。
要稳定拿到PGobject类型
如果就想一直拿到PGobject,那显式指定字段时别加类型参数就行,或者关闭jOOQ的自动类型转换(但不推荐,会影响其他类型的正常处理)。不过这种方式不如指定类型的方案可靠,万一表结构变了容易出问题。
总结
类型差异的关键就是jOOQ有没有拿到列的精确元数据。只要你固定查询写法(要么用select *,要么显式指定字段类型),就能稳定依赖某一种类型。更推荐显式指定字段类型的方式,既让查询逻辑更清晰,又能保证类型一致。
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

