Home > Software design >  JPA: element collection join table on non-PK column
JPA: element collection join table on non-PK column

Time:08-09

In a JPA setup, I have a graph-like structure of entities, featuring classes like:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Vertex {

    @Id
    private String id;

    @ManyToOne
    private Scope parent;

    @Column(name = "visibility_policy")
    private String visibilityPolicy;

    // ...

}

and

@Entity
public class Scope extends Vertex {

    @OneToMany(mappedBy = "parent")
    private final Set<Vertex> children= new HashSet<>();

    @ElementCollection
    @CollectionTable(name = "vertex", joinColumns = @JoinColumn(name = "parent_id", referencedColumnName = "id"))
    @MapKeyColumn(name = "id")
    @Column(name = "visibility_policy")
    private final Map<String, String> childrenVisibility = new HashMap<>(); // how to get this to work?

    // ...

}

What I would like to do is to join this vertex table on itself (id on parent_id) to find all the children of an entity, then get a map that maps any child's id to its visibilityPolicy.

The code above throws the following exception, followed by the usual Spring-Bean-Initialization Stack trace:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.MappingException: Foreign key (FKcjf5jdhsaxodbfg76lath3s5c:alias [id])) must have same number of columns as the referenced primary key (vertex [parent_id,vertex_id])

How can I implement this correcctly?

I feel like I'm way out of my league here, please help :)

CodePudding user response:

Just in case someone struggles with a similar problem, here's how I worked around it:

I made a separate entity that reads from the same table as the children I would have wanted to get the data from. (possible with @Table(name = "my_entity")) Within that pseudo-entity-class I only specified the field I was interested in, so there is no unnecessary data loaded. This now also allows the parent to have an eagerly-fetched collection of its children (well, not the full children but only what's absolutely necessary of them) without severe performance drawbacks.

  • Related