@MapKey引用嵌入映射值内映射列触发AnnotationException的问题咨询
解决@MapKey引用嵌入值已映射列导致的AnnotationException问题
我之前也踩过Hibernate这个坑,刚好能帮你理清问题和解决办法:
问题根源
你现在的代码里,@MapKey(name = "userProfileType")是想把UserProfile里的属性作为Map的键,但UserProfile是@Embeddable类,它的属性本身会被映射到user_profile表的列中。这就导致Hibernate认为同一列被重复映射了,所以抛出AnnotationException。
正确的解决方案
你需要把@MapKey换成@MapKeyColumn,让Hibernate单独为Map的键创建一列,而不是复用嵌入类里已有的映射属性。具体代码调整如下:
首先修改User实体的Map属性配置:
@Entity @Table(name = "user_") public class User extends AbstractEntity<UserId> { // 其他属性省略... @ElementCollection @CollectionTable(name = "user_profile") // 用@MapKeyColumn指定键对应的数据库列名 @MapKeyColumn(name = "user_profile_type") // 直接在这里指定枚举的存储格式 @Enumerated(EnumType.STRING) private Map<UserProfileType, UserProfile> userProfiles; }
然后调整你的UserProfile嵌入类,移除userProfileType属性——因为这个值现在作为Map的键被管理,不需要再作为嵌入类的一部分存储:
@Embeddable @NoArgsConstructor(access = PACKAGE) @AllArgsConstructor public class UserProfile { // 只保留你的用户 profile 相关属性,比如: private String bio; private LocalDate birthday; // 其他属性和方法... }
为什么这能解决问题?
@MapKeyColumn是专门为@ElementCollection的Map结构设计的,它会在集合表(user_profile)中生成一列来存储Map键的枚举值,和嵌入类的属性映射完全分开,不会冲突。- 把
@Enumerated直接放在Map属性上,替代原来的@MapKeyEnumerated,更符合Hibernate的映射规范。
这样调整后,Hibernate就能正确解析你的映射关系,不会再抛出异常啦。
内容的提问来源于stack exchange,提问作者craftingjava
相关产品推荐
相关产品推荐

