如何用注解重写@MappedSuperclass子类的关联映射属性?
如何用JPA注解重写父类的多对多关联表?
没问题,我来帮你把之前的XML配置逻辑转换成JPA注解实现,正好可以用你提到的@AssociationOverrides和@JoinTable来搞定这个需求。
首先先回顾你的基础结构,父类是标记为@MappedSuperclass的抽象类:
@MappedSuperclass public class AbstractEntity{ @ManyToMany protected Set<UserGroupAccess> userGroupAccesses = new HashSet<>(); @ManyToMany protected Set<UserAccess> userAccesses = new HashSet<>(); // 记得添加getter/setter方法 }
接下来,针对Project实体,我们需要用@AssociationOverrides注解来覆盖父类中两个多对多关联的映射规则,每个关联对应一个@AssociationOverride,并在里面通过@JoinTable定义自定义的关联表信息,同时保留XML里的缓存、级联和唯一性配置:
@Entity @Cacheable @AssociationOverrides({ @AssociationOverride( name = "userGroupAccesses", joinTable = @JoinTable( name = "projectusergroupaccesses", joinColumns = @JoinColumn(name = "projectid"), inverseJoinColumns = @JoinColumn(name = "usergroupaccessid", unique = true) ), cache = @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) ), @AssociationOverride( name = "userAccesses", joinTable = @JoinTable( name = "projectuseraccesses", joinColumns = @JoinColumn(name = "projectid"), inverseJoinColumns = @JoinColumn(name = "useraccessid", unique = true) ), cache = @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) ) }) public class Project extends AbstractEntity{ // 其他属性 // 重写父类的属性并指定级联规则(因为级联属于关联的一部分,需要在这里明确) @Override @ManyToMany(cascade = {CascadeType.ALL, CascadeType.DELETE_ORPHAN}) public Set<UserGroupAccess> getUserGroupAccesses() { return super.getUserGroupAccesses(); } @Override @ManyToMany(cascade = {CascadeType.ALL, CascadeType.DELETE_ORPHAN}) public Set<UserAccess> getUserAccesses() { return super.getUserAccesses(); } }
关键注解说明:
@AssociationOverrides:用来批量覆盖父类中多个关联属性的映射配置,里面可以包含多个@AssociationOverride@AssociationOverride:指定要覆盖的父类属性名(name属性),并通过joinTable自定义关联表的结构@JoinTable:name:对应XML中的table属性,指定关联表的名称joinColumns:对应XML中的key标签,设置当前实体在关联表中的外键列inverseJoinColumns:对应XML中的many-to-many标签的column属性,设置关联实体在关联表中的外键列,unique=true对应XML里的unique属性
@Cache:对应XML中的<cache>标签,配置缓存策略@ManyToMany(cascade = {...}):对应XML中的cascade属性,这里需要在子类重写getter方法时指定级联规则,因为父类的级联配置不会被自动继承覆盖
对于TodoTask实体,写法完全类似,只需要把关联表名和外键列改成对应的名称即可:
@Entity @Cacheable @AssociationOverrides({ @AssociationOverride( name = "userGroupAccesses", joinTable = @JoinTable( name = "todotaskusergroupaccesses", joinColumns = @JoinColumn(name = "todotaskid"), inverseJoinColumns = @JoinColumn(name = "usergroupaccessid", unique = true) ), cache = @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) ), @AssociationOverride( name = "userAccesses", joinTable = @JoinTable( name = "todotaskuseraccesses", joinColumns = @JoinColumn(name = "todotaskid"), inverseJoinColumns = @JoinColumn(name = "useraccessid", unique = true) ), cache = @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) ) }) public class TodoTask extends AbstractEntity{ // 其他属性 @Override @ManyToMany(cascade = {CascadeType.ALL, CascadeType.DELETE_ORPHAN}) public Set<UserGroupAccess> getUserGroupAccesses() { return super.getUserGroupAccesses(); } @Override @ManyToMany(cascade = {CascadeType.ALL, CascadeType.DELETE_ORPHAN}) public Set<UserAccess> getUserAccesses() { return super.getUserAccesses(); } }
这样每个子类就会拥有独立的关联表,完全对应你之前XML配置的效果。
内容的提问来源于stack exchange,提问作者Hamza
相关产品推荐
相关产品推荐

