Grails中HQL更新语句出现'id列WHERE子句歧义'问题求助
问题描述
我有一个继承自Registration的RaceRegistration领域类:
class RaceRegistration extends Registration{
Registration类设置了tablePerHierarchy为false,因此数据库中存在registration和race_registration两张独立表:
abstract class Registration extends BaseEntity implements Serializable{ static mapping = { tablePerHierarchy false
执行以下HQL更新语句时:
RaceRegistration.executeUpdate('update RaceRegistration r set r.raceParticipant.bibNumber = null where r.id in (:ids)', [ ids: ids])
抛出如下异常:
ERROR util.JDBCExceptionReporter: Column 'id' in where clause is ambiguous ERROR errors.GrailsExceptionResolver: MySQLIntegrityConstraintViolationException occurred when processing request: [GET] /roadrace/bibs/reassignBibNumbers/976945 - parameters: sort: asc Column 'id' in where clause is ambiguous. Stacktrace follows: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'id' in where clause is ambiguous at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.Util.getInstance(Util.java:386) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4098)
推测是由于存在两张表,HQL无法确定r.id对应的是registration表还是race_registration表。请问如何在HQL语句中消除这种歧义?
解决方案
因为采用了**每个子类一张表(Table Per Subclass)**的映射策略,RaceRegistration对应的数据库表会与父类Registration的表关联,两张表均包含id字段,导致HQL生成SQL时出现字段歧义。
可以通过以下几种方式解决:
明确引用父类实体的id属性
利用Grails ORM的关联特性,直接通过子类关联的父类属性指定id,这是最符合HQL面向对象风格的方式:RaceRegistration.executeUpdate('update RaceRegistration r set r.raceParticipant.bibNumber = null where r.registration.id in (:ids)', [ ids: ids])使用子类表的外键字段名
如果知道数据库中race_registration表关联registration表的外键字段名(比如默认生成的registration_id),可以直接在HQL中引用该字段(用反引号包裹避免关键字冲突):RaceRegistration.executeUpdate('update RaceRegistration r set r.raceParticipant.bibNumber = null where r.`registration_id` in (:ids)', [ ids: ids])显式关联父类后指定id
在HQL中通过JOIN显式关联父类,明确指定id的来源:RaceRegistration.executeUpdate('update RaceRegistration r join r.registration reg set r.raceParticipant.bibNumber = null where reg.id in (:ids)', [ ids: ids])
优先推荐第一种方案,完全基于实体属性操作,不依赖数据库具体字段名,代码可维护性更强。
内容的提问来源于stack exchange,提问作者kofhearts
相关产品推荐
相关产品推荐

