spring data jpa 实体类中字段不与数据库表映射 ORA-00904 标识符无效

本文介绍在使用SpringDataJPA进行开发时,如何解决因实体类中存在与数据库表字段不对应的成员变量而引发的错误。通过添加@Transient注解,可以避免这些成员变量被误识别为数据库字段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当我们使用spring data jpa开发的时候,会将实体类中的成员变量与表中的字段一一对应,当我们在实体类中加上一个不与数据库表一一对应的成员变量的时候,此时会报错,例如:

Caused by: java.sql.SQLSyntaxErrorException: ORA-00904: "BOOK0_"."TYPENAMES": 标识符无效

此时我们只要在这个成员变量上加上注解@Transient即可,例如:

@Transient
private String[] typeNames;




package com.dahsing.model; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import lombok.Data; import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @Entity @Data @Table(name = "MSN_NOA_DATA", schema = "BOSS") public class NOAObject { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "template_provide_date", nullable = false) private Date templateProvideDate; @Column(name = "target_production_deployment_date", nullable = false) private Date targetProductionDeploymentDate; @Column(name = "target_uat_ready_date", nullable = false) private Date targetUATReadyDate; @Column(name = "target_uat_sign_off_date", nullable = false) private Date targetUATSignOffDate; @Column(name = "production_change_submit_time", nullable = false) private Date productionChangeSubmitTime; @OneToMany(mappedBy = "noaObject", orphanRemoval = true) private Set<StatusMapping> statusMappings = new LinkedHashSet<>(); @Column(name = "number_of_response") private int numberOfRespond; // NOA schedule title @Column(name = "scr", nullable = false) private String scr; @Column(name = "desc", nullable = false) private String desc; @Column(name = "template_type") private String templateType; @Column(name = "templateId") private String templateId; @Column(name = "requester", nullable = false) private String requester; @Column(name = "requester_email") private String requesterEmail; @OneToMany(mappedBy = "noaObject", orphanRemoval = true) private List<Task> task; @Column(name = "comment") private String comment; } 2025-07-18T10:18:42.584+08:00 WARN 12568 --- [ restartedMain] o.h.t.s.i.ExceptionHandlerLoggedImpl : GenerationTarget encountered exception accepting comma nd : Error executing DDL "create table boss.msn_noa (id number(19,0) generated as identity, comment varchar2(255 char), desc varchar2(255 char) not null, number_ of_response number(10,0), production_change_submit_time timestamp(6) not null, requester varchar2(255 char) not null, requester_email varchar2(255 char), scr var char2(255 char) not null, target_production_deployment_date timestamp(6) not null, target_uat_ready_date timestamp(6) not null, target_uat_sign_off_date timestam p(6) not null, template_id varchar2(255 char), template_provide_date timestamp(6) not null, template_type varchar2(255 char), primary key (id))" via JDBC [ORA-00904: : invalid identifier ] org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table boss.msn_noa (id number(19,0) generated as identity, comment varchar2 (255 char), desc varchar2(255 char) not null, number_of_response number(10,0), production_change_submit_time timestamp(6) not null, requester varchar2(255 char) not null, requester_email varchar2(255 char), scr varchar2(255 char) not null, target_production_deployment_date timestamp(6) not null, target_uat_ready_date tim estamp(6) not null, target_uat_sign_off_date timestamp(6) not null, template_id varchar2(255 char), template_provide_date timestamp(6) not null, template_type varchar2(255 char), primary key (id))" via JDBC [ORA-00904: : invalid identifier
最新发布
07-19
<think>我们正在解决Hibernate在创建时出现的ORA-00904错误。这个错误通常示在生成的SQL语句中使用了无效标识符字段名或名)。根据用户的问题,我们关注的是实体类数据库字段映射问题。 可能的原因及解决方案: 1. **字段名或名是Oracle的保留关键字**:如果实体类字段名或Oracle的保留关键字冲突,会导致此错误。解决方案是使用转义(双引号)或重命名。 2. **字段名在数据库存在**:可能是由于实体类字段数据库列名一致(比如大小写问题,或者使用了错误的列名)。 3. **实体类字段数据库映射正确**:检查`@Column`注解的name属性是否数据库中的列名完全一致(包括大小写,Oracle默认大写)。 4. **数据库结构未更新**:如果使用了Hibernate的自动建(如hibernate.hbm2ddl.auto=update),可能由于旧的结构存在而无法正确更新。 具体步骤: 步骤1:检查实体类映射 确保每个字段的`@Column`注解中指定的列名在数据库中是有效的。如果列名是Oracle的保留字,需要用双引号括起来,例如: ```java @Column(name = "\"ORDER\"") private String order; ``` 步骤2:检查名 同样,如果名是保留字,也需要用双引号: ```java @Table(name = "\"ORDER\"") ``` 步骤3:开启Hibernate SQL日志 在application.properties中设置: ```properties spring.jpa.show-sql=true logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE ``` 这样可以看到Hibernate生成的SQL语句,从而定位到具体是哪个标识符无效。 步骤4:检查生成的SQL语句 在日志中查找创建的语句,例如: ```sql create table order (id number(19,0) not null, ...) ``` 如果名或字段名是保留字,那么执行时会报ORA-00904错误。 步骤5:修改保留字字段名/名 如果发现是保留字问题,建议修改实体类字段名和对应的`@Column`的name为一个非保留字。如果必须使用,则按照步骤1和2用双引号转义。 步骤6:检查数据库连接用户是否有创建的权限 有时候错误可能是因为权限足,导致无法创建字段。 步骤7:检查数据库结构 如果已经存在,且结构一致,可以考虑先删除(在开发环境)或者使用hibernate.hbm2ddl.auto=update(但注意生产环境慎用)。 步骤8:使用正确的方言 确保在配置文件中指定了正确的Oracle方言,例如: ```properties spring.jpa.database-platform=org.hibernate.dialect.Oracle12cDialect ``` 示例:假设实体类中有一个字段名为"desc",而"DESC"是Oracle的保留字(降序关键字),则应该修改字段名或使用转义: ```java @Column(name = "\"DESC\"") private String description; ``` 注意:在Oracle中,标识符默认是大写的。如果我们在注解中写小写,Hibernate会将其转换成大写,除非使用双引号。因此,如果数据库中的列名是小写(创建时用双引号),那么我们在注解中必须使用双引号并指定小写。 如果问题仍然存在,请提供具体的实体类代码片段和生成的SQL语句,以便进一步分析。 相关问题: 1. 如何查看Oracle的保留关键字? 2. Hibernate中如何配置自动更新数据库结构? 3. 在Oracle数据库中,如何查询一个的结构? 4. 如何解决Hibernate映射中大小写敏感的问题? 5. Hibernate中如何使用自定义命名策略?</think>### 🔍 解决 Hibernate 创建时的 ORA-00904 错误(无效标识符) 当 Hibernate 自动生成 DDL 语句时出现 ORA-00904 错误,通常是由于实体类字段 Oracle 保留字冲突或命名规范匹配导致的。以下是完整解决方案: --- ### 🛠️ 核心解决步骤 #### 1. **检查保留字冲突**(关键) Oracle 保留字如 `ORDER`, `USER`, `LEVEL`, `DATE` 等能直接用作列名。 ```java // 错误示例(使用保留字) @Column(name = "order") // "ORDER" 是 Oracle 保留字 private String order; // 解决方案:添加双引号转义 @Column(name = "\"order\"") // 生成 SQL: "order" VARCHAR2(255) private String order; ``` #### 2. **验证命名策略** Oracle 默认将未转义的标识符转为大写: ```java // 实体类字段 @Column(name = "userName") // 生成 SQL: USERNAME // 若数据库要求小写,需强制转义: @Column(name = "\"userName\"") // 生成 SQL: "userName" ``` #### 3. **配置全局命名策略** 在 `application.properties` 中: ```properties # 强制使用字面名称(转换大小写) spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl # 或自定义策略(处理保留字) spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl ``` #### 4. **检查字段类型映射** ```java // 确保日期类型正确映射 @Column(name = "create_time") @Temporal(TemporalType.TIMESTAMP) // 明确指定类型 private Date createTime; ``` #### 5. **启用 DDL 日志** 在 `application.properties` 添加: ```properties logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.type=TRACE spring.jpa.show-sql=true ``` 日志将显示实际执行的 SQL,例如: ```sql CREATE TABLE my_table ( "order" VARCHAR2(255), -- 转义后的保留字 create_time TIMESTAMP -- 正确映射的日期 ) ``` --- ### 🔬 调试流程 1. **检查生成的 DDL 语句** 在日志中搜索 `create table` 语句,确认: - 是否有未转义的保留字 - 字段名是否意外大写/小写 - 数据类型是否匹配 2. **简化实体类测试** 注释所有字段,逐个取消注释测试,定位问题字段。 3. **数据库权限验证** 确保 Hibernate 使用的数据库用户有 CREATE TABLE 权限: ```sql GRANT CREATE TABLE TO your_hibernate_user; ``` --- ### 💡 预防措施 1. **避免使用保留字** 使用字段名前缀: ```java @Column(name = "ord_status") // 替代 "order" private String orderStatus; ``` 2. **统一命名规范** 在实体类中显式声明列名: ```java @Entity @Table(name = "\"my_table\"") // 名也需转义 public class MyEntity { @Column(name = "\"user\"") // 字段转义 private String user; } ``` 3. **使用 DDL 自动验证** ```properties spring.jpa.hibernate.ddl-auto=validate # 启动时验证实体结构 ``` --- ### 📚 相关问题 1. 如何查询 Oracle 的所有保留关键字? ```sql SELECT * FROM V$RESERVED_WORDS WHERE keyword LIKE '%ORDER%'; ``` 2. Hibernate 中如何自定义物理命名策略? ```java public class CustomNamingStrategy extends PhysicalNamingStrategyStandardImpl { @Override public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) { return Identifier.toIdentifier("col_" + name.getText()); // 添加前缀 } } ``` 3. 实体类继承时如何避免 ORA-00904 错误? 使用 `@MappedSuperclass` 确保父类字段被正确映射。 4. 如何解决 Oracle 中 `@ManyToMany` 中间无效标识符错误? 显式定义中间列名: ```java @JoinTable( name = "\"user_role\"", joinColumns = @JoinColumn(name = "\"user_id\""), inverseJoinColumns = @JoinColumn(name = "\"role_id\"") ) ``` 5. 使用 Hibernate 时如何安全地执行 DDL 更新? ```properties spring.jpa.hibernate.ddl-auto=update # 仅更新结构 spring.jpa.properties.hibernate.hbm2ddl.auto=update ``` > 示例错误分析: > 若日志显示 `CREATE TABLE USER (id NUMBER)` 将失败, > 因 `USER` 是保留字,需改为 `CREATE TABLE "user" (...)`[^1]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值