使用@NamedNativeQuery映射含外键实体时抛出无效列名异常
解决@NamedNativeQuery关联实体映射时的“无效列名”异常
嘿,我瞅了下你的代码,你遇到的「java.sql.SQLException: Nombre de columna no válido」问题,核心原因是原生SQL查询的列和SqlResultSetMapping的映射完全不匹配,还有部分实体属性需要的列在SQL里根本没查出来,下面我一步步给你捋清楚怎么修正:
1. 先改SqlResultSetMapping里的字段对应错误
你写的@SqlResultSetMapping里有两个明显的错误:
- 你把
BedeCategoriaHora的descripcion属性映射到了DESC_ESTADO列(这是状态表的描述),但这个属性本来应该对应分类表自己的DESCRIPCION列啊! - 关联的
codigoEstado属性(BedeEstados类型)的映射也错了,而且你还单独声明了一个BedeEstados的@EntityResult,这会导致Hibernate试图重复映射,反而引发列名冲突。
2. 补充SQL里缺失的列
你的原生SQL只查了状态表的CODIGO_ESTADO和DESCRIPCION,但在映射里却要取HABILITADO、USUARIO_ULTIMA_MODIFICACION这些列,数据库当然找不到,直接抛异常了。得把这些列加到SQL里,还要给它们起唯一别名,避免和分类表的同名字段冲突。
3. 修正后的完整代码
修正后的@NamedNativeQuery
@NamedNativeQuery(name = "BedeCategoriaHora.obtenerCategorias", query ="SELECT * FROM " + "(SELECT q.*, rownum rn FROM " + "(SELECT ct.*, " + " e.CODIGO_ESTADO AS COD_ESTADO, E.DESCRIPCION AS DESC_ESTADO," + " e.HABILITADO AS ESTADO_HABILITADO," + " e.USUARIO_ULTIMA_MODIFICACION AS ESTADO_USUARIO_MOD," + " e.FECHA_ULTIMA_MODIFICACION AS ESTADO_FECHA_MOD" + " FROM schema.BEDE_CATEGORIA_HORA ct, schema.BEDE_ESTADOS e" + " WHERE ct.CODIGO_ESTADO = e.CODIGO_ESTADO" + " AND ct.CODIGO_CATEGORIA LIKE :pFiltroIdRegistro" + " AND UPPER(ct.DESCRIPCION) LIKE :pFiltroDescripcion " + "ORDER BY ct.CODIGO_CATEGORIA)" + " q) " + "WHERE rn BETWEEN :pPrimerRegistro AND :pUltimoRegistro", resultSetMapping = "obtenerCategoriasEntidad")
修正后的@SqlResultSetMapping
@SqlResultSetMapping(name = "obtenerCategoriasEntidad", entities = { @EntityResult(entityClass = BedeCategoriaHora.class, fields = { // 注意:name是实体类的驼峰属性名,不是数据库大写列名 @FieldResult(name = "codigoCategoria", column = "CODIGO_CATEGORIA"), @FieldResult(name = "descripcion", column = "DESCRIPCION"), // 直接通过关联属性的子属性映射,不用单独声明BedeEstados的EntityResult @FieldResult(name = "codigoEstado.codigoEstado", column = "COD_ESTADO"), @FieldResult(name = "codigoEstado.descripcion", column = "DESC_ESTADO"), @FieldResult(name = "codigoEstado.habilitado", column = "ESTADO_HABILITADO"), @FieldResult(name = "codigoEstado.usuarioUltimaModificacion", column = "ESTADO_USUARIO_MOD"), @FieldResult(name = "codigoEstado.fechaUltimaModificacion", column = "ESTADO_FECHA_MOD"), @FieldResult(name = "topeHoras", column = "TOPE_HORAS"), @FieldResult(name = "objetoGasto", column = "OBJETO_GASTO"), @FieldResult(name = "usuarioUltimaModificacion", column = "USUARIO_ULTIMA_MODIFICACION"), @FieldResult(name = "fechaUltimaModificacion", column = "FECHA_ULTIMA_MODIFICACION"), } ) })
几个关键注意事项
- 属性名要严格匹配:
@FieldResult的name必须和实体类的驼峰属性名完全一致,比如实体里是codigoCategoria,就不能写CODIGO_CATEGORIA。 - 关联实体的映射方式:直接用
关联属性名.子属性名的方式映射,不需要单独加另一个@EntityResult,这样能避免同名字段的冲突。 - 列别名要唯一:两个表都有
USUARIO_ULTIMA_MODIFICACION这类字段,一定要给状态表的字段起独特的别名,比如ESTADO_USUARIO_MOD,不然Hibernate会搞混到底取哪个列。
内容的提问来源于stack exchange,提问作者David Fallas
相关产品推荐
相关产品推荐

