AixNPanes
AixNPanes

Reputation: 1260

null not allowed for column in join table with one entity extending another

I have a situation where I have an entity VCenterDistributedVirtualPortgroup which extends VCenterNetwork and both entities are in a OneToMany relationship inside the entity VCenterFolder. I'm getting the following error:

Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "NETWORK_TYPE"; SQL statement: insert into folder_network (folder_type, folder_val, distributedVirtualPortgroups_type, distributedVirtualPortgroups_val) values (?, ?, ?, ?) [23502-182]

VCenterNetwork:

@Entity
@Embeddable
@Table(name="network")
@DiscriminatorColumn(name="discriminator")
@DiscriminatorValue("Network")
public class VCenterNetwork
{
    @Transient
    private Network network;

    @Transient
    private static Map<MOR, VCenterNetwork> networkMap = new TreeMap<MOR, VCenterNetwork>();

    @EmbeddedId
    private MOR id;
    public MOR getId() {return this.id;}
    public void setId(MOR id) {this.id = id;}
    ...
}

VCenterDistributedVirtualPortgroup:

@Entity
@Table(name="distributedvirtualportgroup")
@DiscriminatorColumn(name="discriminator")
@DiscriminatorValue("DistributedVirtualPortgroup")
public class VCenterDistributedVirtualPortgroup extends VCenterNetwork
{
    @Transient
    private DistributedVirtualPortgroup distributedVirtualPortgroup;

    @Transient
    private static Map<MOR, VCenterDistributedVirtualPortgroup> distributedVirtualPortgroupMap = new TreeMap<MOR, VCenterDistributedVirtualPortgroup>();
    ...
}

VCenterFolder:

@Entity
@Table(name="folder")
public class VCenterFolder
{
    @Transient
    private Folder folder;

    @Transient
    private static Map<MOR, VCenterFolder> folderMap = new TreeMap<MOR, VCenterFolder>();

    @EmbeddedId
    private MOR id;
    public MOR getId() {return this.id;}
    public void setId(MOR id) {this.id = id;}

    @Embedded
    @OneToMany(cascade=CascadeType.ALL)
    private List<VCenterNetwork> network = new ArrayList<VCenterNetwork>();
    public List<VCenterNetwork> getNetwork() {return this.network;}
    public void getvirtualNetwork(List<VCenterNetwork> network) {this.network = network;}

    @Embedded
    @OneToMany(cascade=CascadeType.ALL)
    private List<VCenterDistributedVirtualPortgroup> distributedVirtualPortgroups = new ArrayList<VCenterDistributedVirtualPortgroup>();
    public List<VCenterDistributedVirtualPortgroup> getDistributedVirtualPortgroups() {return this.distributedVirtualPortgroups;}
    public void setDistributedVirtualPortgroups(List<VCenterDistributedVirtualPortgroup> distributedVirtualPortgroups){this.distributedVirtualPortgroups = distributedVirtualPortgroups;}
    ....
}

This results in a join table that looks like the following:

FOLDER_NETWORK
    FOLDER_TYPE - VARCHAR(255) NOT NULL
    FOLDER_VAL - VARCHAR(255) NOT NULL
    NETWORK_TYPE - VARCHAR(255) NOT NULL
    NETWORK_VAL - VARCHAR(255) NOT NULL
    DISTRIBUTEDVIRTUALPORTGROUP_TYPE - VARCHAR(255) NOT NULL
    DISTRIBUTEDVIRTUALPORTGROUP_TYPE - VARCHAR(255) NOT NULL

I'm new to JPA, but my guess is that a join table is needed for both VCenterFolder-VCenterNetwork and VCenterFolder-VCenterDistributedVirtualPortgroup, but since VCenterDistributedVirtualPortgroup extends VCenterNetwork, it's building one join table with both relations but using a different type/val pair for each relation. I would assume that only one pair will be used at a time with the other being null. That seems to be a problem. It would seem to me that the fields should either be nullable or the two sets of type/val pairs should be merged into one.

I assume there is some way round this, but I sure don't know what it is.

Upvotes: 1

Views: 936

Answers (1)

AixNPanes
AixNPanes

Reputation: 1260

MOR happens to have the members type & val, thus the names in the join table.

I solved the problem by adding the folloing JoinTable on both the network and distributedVirtualPortgroups fields:

    @JoinTable
    (
            name="FOLDER_NETWORK",
            joinColumns= {@JoinColumn(name="TYPE", referencedColumnName="TYPE"), @JoinColumn(name="VAL", referencedColumnName="VAL")},
            inverseJoinColumns= {@JoinColumn(name="NETWORK_TYPE", referencedColumnName="TYPE"), @JoinColumn(name="NETWORK_VAL", referencedColumnName="VAL")}
    )

Upvotes: 2

Related Questions