MyBatis映射Oracle ROWID字段报错或为null的根本原因是其未被MyBatis内置类型映射支持,必须通过resultMap显式映射为String类型属性(如rowId),并配合SQL中ROWID AS row_id别名使用,不可依赖resultType自动映射或驼峰转换。
MyBatis映射Oracle ROWID 字段时为什么报错或为null
根本原因不是类型不匹配,而是mybatis默认不识别rowid这个oracle特有伪列类型——它既不是标准jdbc类型,也不在mybatis内置类型映射表中。即使你用string接收,若未显式声明字段映射,mybatis会跳过该列(尤其在resulttype自动映射模式下),导致值为null。
ROWID 必须显式映射,不能依赖resultType自动推导
MyBatis的resultType只按列名+Java Bean属性名做简单驼峰/下划线匹配,而ROWID在SQL中若没起别名(如SELECT ROWID AS row_id),返回的列名就是大写的ROWID,与Java属性rowId或rowid均不匹配;即使起了别名,也需确保resultMap中明确定义。
- 必须使用
resultMap,而非resultType -
<result property="rowId" column="ROWID"></result>写法无效:Oracle驱动返回的列名是ROWID,但JDBC元数据可能报告为ROWID或空字符串,稳妥做法是显式别名:SELECT t.*, ROWID AS row_id FROM your_table t -
property名建议用rowId(首字母小写+大写D),避免和Oracle内置ROWID关键字混淆
用String接收ROWID是合理且安全的
Oracle ROWID本质是base64编码的物理地址字符串(如AAAS7mAABAAANRRAAA),JDBC驱动默认将其映射为String,无需自定义TypeHandler。但要注意:
- 实体类字段类型必须是
String,不可用Long、BigInteger等数值类型 - 不要对
ROWID做算术运算或持久化到业务表——它是临时物理标识,表结构变更、数据迁移后即失效 - 若用于分页(如
BETWEEN :start_rowid AND :end_rowid),必须保证查询期间表无DML操作,否则结果不一致
容易被忽略的兼容性陷阱
同一个ROWID在不同Oracle版本或RAC环境中表现一致,但MyBatis层容易栽在两处:
- Oracle 12c+启用
ENABLE ROW MOVEMENT后,ROWID可能变化,此时用ROWID分页或缓存会出错 - MyBatis-Plus 3.4.3+已内置
OracleRowIdTypeHandler,但仅在selectById等单查场景生效;手写SQL仍需自己映射 - Spring Boot + MyBatis配置中若启用了
mapUnderscoreToCamelCase=true,它对ROWID别名row_id有效,但对原生ROWID列名无效——别依赖这个开关











