这是什么报错Caused by: javax.ejb.EJBException: 查询异常,SQLSyntaxErrorException: ORA-00904: "USEABLE_QTY": invalid identifier
时间: 2025-07-19 10:24:54 浏览: 16
<think>我们遇到了一个SQL异常:ORA-00904: "USEABLE_QTY": invalid identifier
这个错误通常表示在SQL语句中引用了一个不存在的列名。根据错误信息,列名"USEABLE_QTY"在数据库表中不存在。
可能的原因:
1. 数据库表中确实没有这个列。
2. 列名拼写错误(注意大小写,Oracle默认是大写,但如果在创建表时使用了双引号指定小写,则需要使用双引号括起来并区分大小写)。
3. 在SQL语句中引用了错误的列名(可能是别名错误或者列名错误)。
在之前的代码中,我们在Java实体类中使用了属性名,如`useableQty`,然后通过ORM框架(如Hibernate或EclipseLink)将其映射到数据库列。
通常,ORM框架会将驼峰命名的属性转换为下划线分隔的大写形式(即`useableQty` -> `USEABLE_QTY`)。但是,如果数据库中的列名不是这个,就会报错。
解决方案步骤:
1. **检查数据库表结构**:
确认数据库表中是否存在`USEABLE_QTY`列(注意大小写)。如果没有,那么需要检查实际列名是什么。
2. **检查实体类与数据库的映射**:
- 如果使用JPA注解,检查`@Column`注解是否指定了正确的列名。
- 如果没有指定,则默认的命名策略会生成`USEABLE_QTY`,如果数据库列名不同,就需要显式指定。
3. **修改实体类映射**:
假设数据库中的实际列名为`USABLE_QTY`(少了一个E),那么可以在实体类中这样指定:
```java
@Column(name = "USABLE_QTY") // 如果数据库列名是USABLE_QTY
private Integer useableQty;
```
4. **检查SQL查询语句**:
如果使用的是原生SQL查询,那么检查SQL语句中是否写错了列名。
5. **检查查询语句中的列名别名**:
如果查询中使用了别名,确保别名与实体类属性匹配。
具体到我们的代码,我们注意到在`ToolNoteRequestDm`实体类中,我们新增了四个属性:
- useableQty
- unUseableQty
- demageQty
- offQty
默认情况下,ORM框架会将这些属性映射到以下列名:
- useableQty -> USEABLE_QTY
- unUseableQty -> UN_USEABLE_QTY
- demageQty -> DEMAGE_QTY
- offQty -> OFF_QTY
但是,数据库实际列名可能与这些不同。例如,可能拼写错误(如USABLE_QTY少了E)或者使用了不同的命名规则。
因此,我们需要检查数据库表结构,并相应调整实体类的映射。
示例修改:
假设数据库中的列名分别为:
- USABLE_QTY (注意:没有第一个E)
- UNUSABLE_QTY (注意:没有下划线,且少了一个E)
- DAMAGE_QTY (注意:不是DEMAGE,而是DAMAGE)
- FLY_OFF_QTY (注意:列名不是OFF_QTY)
那么,我们需要在实体类中这样指定:
```java
public class ToolNoteRequestDm {
// ... 其他属性 ...
@Column(name = "USABLE_QTY")
private Integer useableQty;
@Column(name = "UNUSABLE_QTY")
private Integer unUseableQty;
@Column(name = "DAMAGE_QTY")
private Integer demageQty;
@Column(name = "FLY_OFF_QTY")
private Integer offQty;
// ... getters and setters ...
}
```
6. **如果使用原生SQL查询**:
在`noteRequestEjb.queryNoteReqByPage`方法中,如果使用了原生SQL,需要确保SQL语句中的列名与数据库一致。例如:
```sql
SELECT
USABLE_QTY AS useableQty,
UNUSABLE_QTY AS unUseableQty,
DAMAGE_QTY AS demageQty,
FLY_OFF_QTY AS offQty,
...
FROM ...
```
7. **验证数据库列名**:
可以使用数据库工具(如SQL Developer)查看表结构,确认列名。
8. **如果数据库中没有这些列**:
那么需要先添加这些列到数据库表中,或者调整查询语句不要包含这些列(如果不需要的话)。
总结:这个错误是因为SQL语句中引用了不存在的列名。我们需要确保在实体类映射或SQL查询中使用的列名与数据库中的实际列名一致。
如果问题仍然存在,请检查EJB中执行查询的代码,特别是原生SQL部分。
由于我们无法直接查看数据库和EJB的具体实现,以上是常见的解决方案。
注意:在Oracle中,如果没有使用双引号创建列名,那么列名默认是大写的。在SQL语句中引用时,大小写不敏感(Oracle会默认转为大写)。但是,如果创建表时使用了双引号指定了小写列名,那么在查询时必须使用双引号括起来并指定小写。一般情况下,建议使用大写列名。
因此,请确保在实体类的`@Column`注解中指定的大写列名与数据库中的列名完全一致(包括大小写)。
如果使用了Hibernate,可以开启SQL日志输出,查看实际生成的SQL语句,从而确定问题。
在`persistence.xml`中配置:
```xml
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
```
或者在Spring Boot中配置:
```properties
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
```
然后检查日志中输出的SQL语句,看是否包含`USEABLE_QTY`,并与实际表结构对比。
最后,如果确定是数据库表缺少字段,那么需要添加这些字段:
```sql
ALTER TABLE tool_note_request
ADD (USABLE_QTY NUMBER(10),
UNUSABLE_QTY NUMBER(10),
DAMAGE_QTY NUMBER(10),
FLY_OFF_QTY NUMBER(10));
```
请根据实际需要调整数据类型和长度。
通过以上步骤,应该可以解决该问题。</think>### ORA-00904 错误分析与解决方案
这个错误 `ORA-00904: "USEABLE_QTY": invalid identifier` 表示 Oracle 数据库无法识别 SQL 查询中引用的列名 `USEABLE_QTY`。这是 Oracle 数据库特有的错误代码,通常由以下原因引起:
#### 错误原因分析
1. **列名拼写错误**:
- Java 实体类属性:`useableQty`
- SQL 查询中可能使用了:`USEABLE_QTY`(注意下划线和大小写)
- Oracle 对标识符区分大小写,当使用双引号包裹时
2. **数据库表结构不匹配**:
- Java 实体类添加了新属性,但数据库表没有相应字段
- 数据库字段名与实体类映射不一致
3. **ORM 映射问题**:
- JPA/Hibernate 的命名策略可能导致转换错误
- 缺少 `@Column` 注解或注解配置错误
#### 解决方案步骤
##### 1. 检查数据库表结构
确认数据库中是否存在 `USEABLE_QTY` 字段(或对应的小写形式):
```sql
-- 查询表结构
DESC tool_note_request;
-- 或者
SELECT column_name
FROM all_tab_columns
WHERE table_name = 'TOOL_NOTE_REQUEST'
AND owner = 'YOUR_SCHEMA';
```
##### 2. 修复实体类映射
在实体类中添加正确的 JPA 注解:
```java
@Entity
@Table(name = "TOOL_NOTE_REQUEST")
public class ToolNoteRequestDm {
// 其他属性...
@Column(name = "USEABLE_QTY") // 确保与数据库列名匹配
private Integer useableQty;
@Column(name = "UN_USEABLE_QTY")
private Integer unUseableQty;
@Column(name = "DEMAGE_QTY")
private Integer demageQty;
@Column(name = "OFF_QTY")
private Integer offQty;
// getter/setter...
}
```
##### 3. 修改 SQL 查询
检查 EJB 中的查询语句,确保列名正确:
```java
// 在查询方法中,确保使用正确的列名
public List<ToolNoteRequestDm> queryNoteReqByPage(...) {
String sql = "SELECT t.id, t.useable_qty, t.un_useable_qty, "
+ "t.demage_qty, t.off_qty ... FROM tool_note_request t";
// 使用原生SQL查询
Query query = entityManager.createNativeQuery(sql, ToolNoteRequestDm.class);
// ...
}
```
##### 4. 更新数据库表结构
如果数据库缺少字段,执行 ALTER TABLE 添加字段:
```sql
ALTER TABLE tool_note_request ADD (
useable_qty NUMBER(10),
un_useable_qty NUMBER(10),
demage_qty NUMBER(10),
off_qty NUMBER(10)
);
```
##### 5. 配置命名策略(可选)
在 `persistence.xml` 中配置物理命名策略:
```xml
<persistence-unit name="yourPU">
<properties>
<!-- 使用下划线分隔的物理命名策略 -->
<property name="hibernate.physical_naming_strategy"
value="org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl"/>
</properties>
</persistence-unit>
```
#### 错误排查流程图
```mermaid
graph TD
A[ORA-00904错误] --> B{数据库列是否存在?}
B -->|是| C{ORM映射是否正确?}
B -->|否| D[执行ALTER TABLE添加字段]
C -->|是| E{SQL查询是否正确?}
C -->|否| F[添加@Column注解]
E -->|是| G[检查大小写和下划线]
E -->|否| H[修正SQL查询]
D --> I[重启应用]
F --> I
H --> I
G --> I
```
#### 常见陷阱及避免方法
1. **大小写敏感问题**:
- Oracle 默认不区分大小写,但使用双引号包裹标识符时会区分
- 统一使用大写字母和下划线命名数据库对象
2. **命名策略冲突**:
- Hibernate 默认将驼峰命名转换为下划线格式
- 显式使用 `@Column(name = "...")` 避免自动转换问题
3. **数据库与代码不同步**:
- 使用 Flyway 或 Liquibase 管理数据库变更
- 确保开发、测试和生产环境数据库结构一致
阅读全文
相关推荐




















