JPA @Entity映射无ID列Oracle表遇ORA-00904错误的解决咨询
解决JPA实体映射无ID列Oracle表的问题
错误原因
你添加@Id + GenerationType.IDENTITY后报错,是因为JPA会根据这个注解生成查询去读取ID列,但你的my_table根本没有这个列,所以Oracle抛出ORA-00904(标识符无效)错误。JPA要求所有实体必须有主键(@Id标注),不能省略,所以可从以下两种方向解决:
方案1:使用现有列作为复合主键
如果你的my_table中,DATE和SUMTYPE的组合是唯一的(无重复行),可以把这两个字段设为复合主键,无需修改数据库表结构。
步骤1:创建主键类
这个类必须实现Serializable,包含要作为主键的字段,并正确重写equals()和hashCode():
@Data @NoArgsConstructor @AllArgsConstructor public class CashFlowPK implements Serializable { private LocalDate date; private String sumType; }
步骤2:修改实体类
用@IdClass指定主键类,并给每个主键字段添加@Id注解:
@Entity @Table(name = "my_table") @Data @NoArgsConstructor @AllArgsConstructor @IdClass(CashFlowPK.class) // 指定主键类 public class CashFlowTrainingData { @Id // 标记为主键字段 @Column(name = "DATE") private LocalDate date; @Id // 标记为主键字段 @Column(name = "SUMTYPE") private String sumType; @Column(name = "SUM") private Double sum; }
方案2:给数据库表添加ID列(推荐,若允许修改表结构)
如果可以修改数据库表,添加一个自增ID列是最省心的方案,符合JPA单主键的常规用法。
步骤1:给Oracle表添加自增ID列
- Oracle 12c及以上支持
IDENTITY自增列,执行SQL:
ALTER TABLE my_table ADD id NUMBER GENERATED ALWAYS AS IDENTITY START WITH 1 INCREMENT BY 1;
- Oracle 11g及以下版本,需手动创建序列和触发器:
-- 创建序列 CREATE SEQUENCE my_table_seq START WITH 1 INCREMENT BY 1; -- 创建触发器,插入时自动赋值ID CREATE OR REPLACE TRIGGER my_table_trigger BEFORE INSERT ON my_table FOR EACH ROW BEGIN SELECT my_table_seq.NEXTVAL INTO :NEW.id FROM DUAL; END; /
步骤2:修改实体类对应ID注解
- Oracle 12c+用IDENTITY策略:
@Entity @Table(name = "my_table") @Data @NoArgsConstructor @AllArgsConstructor public class CashFlowTrainingData { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "DATE") private LocalDate date; @Column(name = "SUMTYPE") private String sumType; @Column(name = "SUM") private Double sum; }
- Oracle 11g及以下用序列策略:
@Entity @Table(name = "my_table") @Data @NoArgsConstructor @AllArgsConstructor public class CashFlowTrainingData { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_table_seq") @SequenceGenerator(name = "my_table_seq", sequenceName = "MY_TABLE_SEQ", allocationSize = 1) private Long id; @Column(name = "DATE") private LocalDate date; @Column(name = "SUMTYPE") private String sumType; @Column(name = "SUM") private Double sum; }
内容的提问来源于stack exchange,提问作者Павлюченко Антон
相关产品推荐
相关产品推荐

