简体   繁体   中英

JPA - many-to-many relationship in abstract base entity class and join table reference in concrete extended entity sub-classes

I have an abstract BaseEntity class, all concrete entity classes extends from it.

Now there is a "tag" entity and each concrete entity class have many-to-many relationship with tag.

Based on my JPA code I am generating SQL Tables thru "persistence.xml" using "javax.persistence.schema-generation.scripts.create-target"

BaseEntity.java

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BaseEntity implements Serializable {

    @Column(name = "uid")
    private Long uid;

    /** 
     * The owning side of a ManyToMany relationship from each entity to Tag
     */
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "baseentity_tag", joinColumns =
    {
        @JoinColumn(name = "baseuid", referencedColumnName = "uid")
    }, inverseJoinColumns =
    {
        @JoinColumn(name = "taguid", referencedColumnName = "uid")
    })
    protected List<Tag> tags = new ArrayList<>();

    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }

    public void setTags(List<Tag> tags) {
        this.tags = tags;
    }

    public List<Tag> getTags() {
        return tags;
    }
}

Tag Entity class

@Entity
public class Tag extends BaseEntity {

    private static final long serialVersionUID = 1L;

    /** 
     * The inverse side of a ManyToMany relationship from Tag to each entity
     */
    @ManyToMany(mappedBy = "tags", fetch = FetchType.LAZY)
    private List<BaseEntity> baseEntities = new ArrayList<>();   

    public void setBaseEntities(List<BaseEntity> baseEntities) {
        this.baseEntities = baseEntities;
    }

    @XmlTransient
    public List<BaseEntity> getBaseEntities() {
        return baseEntities;
    }          
}

Is there any issue with above design; at line

@JoinColumn(name = "baseuid", referencedColumnName = "uid")

because I am expecting join table "baseentity_tag" (column "baseuid" ) to have reference in each concrete entity class, say concrete1.java, concrete2.java etc. ?

I guess a common join table "baseentity_tag" will not suffice the need against all Concrete entities.

This is because the generated SQL code for create statement is:

CREATE TABLE baseentity_tag (baseuid VARCHAR(255) NOT NULL, taguid BIGINT NOT NULL, PRIMARY KEY (baseuid, taguid));
ALTER TABLE baseentity_tag ADD CONSTRAINT FK_baseentity_tag_baseuid FOREIGN KEY (baseuid) REFERENCES conrete1 (uid);
ALTER TABLE baseentity_tag ADD CONSTRAINT FK_baseentity_tag_taguid FOREIGN KEY (taguid) REFERENCES tag (uid);

Here there is no reference to conrete2, concrete3 etc tables.

If so is there any generic solution to this or I need to create separate @ManyToMany relations in each concrete entity class ?

The way you set up your relationships is independent from form the inheritance strategy. So the definition of your @ManyToMany relationship with associated @JoinTable definition should work with all the strategies available – SINGLE_TABLE , JOINED and TABLE_PER_CLASS – all of which have different set of tables to support the strategy.

In your case you have selected strategy InheritanceType.TABLE_PER_CLASS , so each of your concrete classes will have its own table including fields inherited from the Abstract Super BaseEntity . Each of these tables contains a uid column (as will table Tag ). Each of these concrete classes inherits the @ManyToMany relationship and refers to the JoinTable baseentity_tag which simply links entities based on the uid values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM