JPA ElementCollection外键映射列数错误问题求助
实体类代码
@Entity @Table(name ="my_class", uniqueConstraints = {@UniqueConstraint(name = "AAndBAndCAndD", columnNames = { "A","B","C","D"}) }) public class MyClass implements Serializable { @Id @GeneratedValue(strategy=GenerationType.AUTO) private Integer id; @Column(name = "A") private String A; @Column(name = "B") private String B; @Column(name = "C") private Integer C; @Column(name = "D") private Integer D; @Column(name = "E") private Long E; @ElementCollection(targetClass = String.class, fetch = FetchType.EAGER) @CollectionTable(name="values_table", joinColumns = @JoinColumn(name="some_table_id", referencedColumnName = "id")) @Column(name="values") private Set<String> values; }
手动创建的数据库表
CREATE TABLE some_table ( id serial PRIMARY KEY, A character varying(10) NOT NULL, B character varying(10) NOT NULL, C int NOT NULL, D int NOT NULL, E bigint, UNIQUE (A,B,C,D) ); CREATE TABLE values_table ( some_table_id int NOT NULL, values VARCHAR(500), constraint fk_values_table_some_table foreign key (some_table_id) REFERENCES some_table(id) );
报错信息
Caused by: org.hibernate.MappingException: collection foreign key mapping has wrong number of columns: MyClass.values type: component[id,id]
at org.hibernate.mapping.Collection.validate(Collection.java:309)
at org.hibernate.mapping.Set.validate(Set.java:40)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1364)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1851)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:852)
26 more
已尝试给values表添加Id字段,但问题仍未解决,求排查外键映射错误原因。
解决方案
问题核心是实体类与数据库主表名称不匹配:
- 实体类
MyClass的@Table注解指定表名为my_class,但你手动创建的主表叫some_table,Hibernate会默认去匹配my_class表,实际存在的却是some_table,直接导致映射逻辑混乱。 - 虽然集合表
values_table的配置是对的,但主表名称不匹配会让Hibernate无法正确关联外键关系,最终抛出列数错误的异常。
修复方式二选一:
- 修改实体类的
@Table注解,将表名改为some_table,与数据库实际表名一致:
@Entity @Table(name ="some_table", uniqueConstraints = {@UniqueConstraint(name = "AAndBAndCAndD", columnNames = { "A","B","C","D"}) }) public class MyClass implements Serializable { // 其他代码保持不变 }
- 或者修改数据库主表名称为
my_class,对齐实体类注解配置。
另外,values_table不需要单独加主键,@ElementCollection的集合表默认会用外键+集合元素作为联合主键(针对简单类型元素),你之前手动添加的主键反而会干扰Hibernate的默认映射逻辑,建议移除额外添加的主键,保持原表结构即可。
内容的提问来源于stack exchange,提问作者GoldBug

