Encountered a duplicated sql alias [name] during auto-discovery of a native-sql

博客指出在用原生SQL查询表的某一列时,存在未为查询列设置别名的错误情况。

这个错误是在用原生sql查询表的某一列的时候 没有为查询的列设置别名.

`NonUniqueDiscoveredSqlAliasException: Encountered a duplicated sql alias [FDEPMC] during auto-discovery of a native-sql query` 是 Hibernate 在执行原生 SQL 查询(Native SQL Query)时常见的异常。这个错误表示:**在解析原生 SQL 查询结果映射时,Hibernate 发现了重复的列别名 `FDEPMC`,无法确定该别名对应哪个实体或属性,导致自动发现机制失败。** --- ### 🔍 错误原因分析 当你使用 `createNativeQuery()` 执行原生 SQL 并希望 Hibernate 自动将结果映射到实体对象(如通过 `addEntity()` 或使用 `ResultTransformer`)时,Hibernate 会尝试根据查询返回的列别名(alias)来匹配实体字段。 如果多个列使用了相同的别名(例如都叫 `FDEPMC`),Hibernate 就不知道哪一个才是目标字段,于是抛出此异常。 常见场景包括: - 多表连接中未对同名列进行唯一别名处理; - 手动写 SQL 时不小心用了重复的 `AS FDEPMC`; - 使用数据库关键字或默认导出列名产生冲突; - 视图或子查询中已经存在 `FDEPMC` 列,又在外层再次暴露。 --- ### ✅ 解决方案 #### 方案一:确保所有列别名唯一(推荐) 修改你的原生 SQL,为每一个列设置唯一的别名,尤其是来自不同表但名称相同的列。 ```sql SELECT t1.dept_code AS FDEPMC_DEPT, t2.emp_code AS FDEPMC_EMP, t1.dept_name AS DEPT_NAME, t2.emp_name AS EMP_NAME FROM departments t1 JOIN employees t2 ON t1.id = t2.dept_id ``` 然后在 Java 中使用: ```java List<Object[]> results = session.createNativeQuery( "SELECT " + "t1.dept_code AS FDEPMC_DEPT, " + "t2.emp_code AS FDEPMC_EMP, " + "t1.dept_name AS DEPT_NAME, " + "t2.emp_name AS EMP_NAME " + "FROM departments t1 " + "JOIN employees t2 ON t1.id = t2.dept_id" ).getResultList(); ``` > 这样就不会出现重复的 `FDEPMC` 别名了。 --- #### 方案二:显式定义结果集映射(ResultSetMapping) 如果你必须使用重复别名(不建议),可以创建一个明确的 `SqlResultSetMapping` 来告诉 Hibernate 如何映射每一列。 ##### 步骤 1:定义 `@SqlResultSetMapping` ```java @Entity @SqlResultSetMapping( name = "DepartmentEmployeeMapping", entities = @EntityResult( entityClass = Department.class, fields = { @FieldResult(name = "code", column = "FDEPMC_DEPT"), @FieldResult(name = "name", column = "DEPT_NAME") } ), columns = { @ColumnResult(name = "EMP_NAME"), @ColumnResult(name = "FDEPMC_EMP") } ) @Table(name = "departments") public class Department { // ... } ``` ##### 步骤 2:使用命名映射执行查询 ```java Query query = session.createNativeQuery( "SELECT " + "d.dept_code AS FDEPMC_DEPT, " + "e.emp_code AS FDEPMC_EMP, " + "d.dept_name AS DEPT_NAME, " + "e.emp_name AS EMP_NAME " + "FROM departments d " + "JOIN employees e ON d.id = e.dept_id", "DepartmentEmployeeMapping" ); List<Object[]> results = query.getResultList(); ``` 这种方式绕过了“自动发现”过程,因此不会触发 `NonUniqueDiscoveredSqlAliasException`。 --- #### 方案三:避免自动映射 —— 使用 Object[] 或 Map 接收结果 最简单的方式是不要让 Hibernate 去自动映射实体,而是手动处理结果。 ```java List<Object[]> results = session.createNativeQuery( "SELECT d.dept_code AS FDEPMC, e.emp_code AS FDEPMC, d.dept_name, e.emp_name " + "FROM departments d JOIN employees e ON d.id = e.dept_id" ).getResultList(); for (Object[] row : results) { String deptCode = (String) row[0]; String empCode = (String) row[1]; // 手动处理,不怕别名重复 } ``` > 注意:虽然 SQL 中有两个 `FDEPMC` 别名,但由于你不使用 `addEntity()` 或自动映射,Hibernate 不会去解析这些别名,所以不会报错。 --- ### ❌ 错误做法(应避免) ```java // 危险!两个列都叫 FDEPMC String sql = "SELECT d.code AS FDEPMC, e.code AS FDEPMC FROM dept d, emp e WHERE ..."; Query q = session.createNativeQuery(sql).addEntity(Dept.class); // 抛异常! ``` 这正是引发 `NonUniqueDiscoveredSqlAliasException` 的典型代码。 --- ### 💡 总结 | 方法 | 是否推荐 | 说明 | |------|----------|------| | 给每列唯一别名 | ✅ 强烈推荐 | 最清晰、最安全 | | 使用 `@SqlResultSetMapping` | ✅ 推荐 | 控制力强,适合复杂映射 | | 返回 `Object[]` 避免映射 | ✅ 实用 | 快速绕过问题 | | 允许重复别名并依赖自动发现 | ❌ 禁止 | 一定会出错 | --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值