JPA原生SQL插入PostgreSQL自定义类型字段报类型不匹配如何解决
问题场景
定义如下JPA Repository原生插入方法:
public interface CMRepository extends JpaRepository <CMark, String> { @Transactional @Modifying @Query(value = "INSERT INTO c_mark(class_fk, s_con_fk, dis_con_fk, rto_fk, version, classification) " + "values(:class_fk, :s_con_fk, :dis_con_fk, :rto_fk, :version, :classification)", nativeQuery = true) int insertCMark(@Param("class_fk") String class_fk, @Param("s_con_fk") String s_con_fk, @Param("dis_con_fk") String dis_con_fk, @Param("rto_fk") String rto_fk, @Param("version") int version, @Param("classification") String classification); }
执行方法时抛出异常:
PSQLException: ERROR: column "classification" is of type classification but expression is of type character varying
报错核心原因是数据库中classification字段为PostgreSQL自定义USER-DEFINED类型,JDBC驱动默认将Java String类型参数映射为character varying(即varchar)类型,PostgreSQL无法自动完成该类型到自定义类型的隐式转换,最终抛出类型不匹配错误。
解决方案
优先选择改造成本最低的SQL显式类型转换方案,直接在原生插入语句中对classification参数做强制类型转换即可,不需要额外引入依赖或修改全局配置。
修改@Query注解中的SQL,将对应参数位置替换为类型转换写法:
@Query(value = "INSERT INTO c_mark(class_fk, s_con_fk, dis_con_fk, rto_fk, version, classification) " + "values(:class_fk, :s_con_fk, :dis_con_fk, :rto_fk, :version, CAST(:classification AS classification))", nativeQuery = true)
也可以使用PostgreSQL原生的简写类型转换语法,效果完全一致:
-- 将对应参数位置替换为以下写法 :classification::classification
注意事项
- 如果自定义的
classification类型不在public schema下,转换时需要补全schema路径,例如CAST(:classification AS 业务schema名.classification) - 如果项目中多处用到该自定义类型,也可以自定义Hibernate类型映射或JPA AttributeConverter统一处理类型转换,避免每次写SQL都加显式转换,但单接口场景下直接改SQL的效率最高。
内容的提问来源于stack exchange,提问作者Timothy Clotworthy
相关产品推荐
相关产品推荐

