Hibernate多对多关联含额外列查询报错:未知列问题
问题:Hibernate处理带额外列的多对多关联时出现未知列错误
我在使用Hibernate处理带有额外列的多对多关联时遇到问题,以下是我的代码:
@Entity public class TransactionEntity extends AbstractBaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long transactionId; /* some fields*/ @OneToMany(mappedBy = "transaction", fetch = FetchType.LAZY) private List<TransactionTagEntity> tags; } @Entity public class TagEntity extends AbstractBaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long tagId; /* some fields*/ @OneToMany(mappedBy = "tag", fetch = FetchType.LAZY) private List<TransactionTagEntity> transactions; } @Entity public class TransactionTagEntity extends AbstractBaseEntity { @EmbeddedId private TransactionTagPk pk; @ManyToOne @MapsId("transactionId") private TransactionEntity transaction; @ManyToOne @MapsId("tagId") private TagEntity tag; } @Embeddable public class TransactionTagPk implements Serializable { @Column(name = "transaction_id") private Long transactionId; @Column(name = "tag_id") private Long tagId; }
当我尝试查询关联了标签的交易(或关联了交易的标签)时,收到如下错误:
Unknown column 't2_0.tag_tag_id' in 'on clause'
或
Unknown column 't2_0.transaction_transaction_id' in 'on clause'
我从未定义过这些列,这是怎么回事?
编辑补充
以下是Hibernate生成的查询语句示例:
select t1_0.transaction_transaction_id, t1_0.tag_tag_id, t2_0.tag_id, t2_0.name, t2_0.note, t2_0.time_create, t2_0.time_update, t2_0.user_create_id, t2_0.user_id, t2_0.user_update_id, t1_0.time_create, t1_0.time_update, t1_0.user_create_id, t1_0.user_update_id from transaction_tag t1_0 left join tag t2_0 on t2_0.tag_id=t1_0.tag_tag_id where t1_0.transaction_transaction_id=?
解决方案
问题原因
Hibernate错误生成了transaction_transaction_id、tag_tag_id这类拼接列名,本质是它默认将关联实体的属性名与对应主键名拼接,比如把TransactionTagEntity里的transaction属性和该属性的主键transactionId组合成transaction_transaction_id,但你的中间表transaction_tag实际列名是transaction_id和tag_id,两者不匹配导致报错。
修复步骤
需要在TransactionTagEntity的@ManyToOne注解上显式指定关联列名,明确告诉Hibernate中间表对应的外键列:
修改后的TransactionTagEntity代码如下:
@Entity public class TransactionTagEntity extends AbstractBaseEntity { @EmbeddedId private TransactionTagPk pk; @ManyToOne @MapsId("transactionId") @JoinColumn(name = "transaction_id") // 显式指定外键列名 private TransactionEntity transaction; @ManyToOne @MapsId("tagId") @JoinColumn(name = "tag_id") // 显式指定外键列名 private TagEntity tag; }
额外说明
虽然你已经在TransactionTagPk中用@Column指定了列名,但Hibernate处理关联映射时仍会默认按属性名+主键名生成外键列名。因此必须通过@JoinColumn明确指定与中间表一致的列名,这样生成的SQL就会正确使用transaction_id和tag_id,避免错误的拼接列名。
内容的提问来源于stack exchange,提问作者Mark116
相关产品推荐
相关产品推荐

