Hibernate - using composite key that contains a parent id - OneToMany

1.2k views Asked by At

(The original question has changed, see updates below.)

I have trouble letting hibernate set the primary key of a child object. The primary key is identical with the parent's primary key.

This is what the parent looks like:

@Entity
@Table(name = "PARENT")
@SequenceGenerator(name = "SEQ", allocationSize = 1, sequenceName = "seq_parent_id")
public class Parent {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ")
    private Long id;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @Fetch(value = FetchMode.SUBSELECT)
    @JoinColumn(name = "PARENT_ID")
    private Set<Child> children;

This is what the child looks like:

@Entity
@Table(name = "CHILDREN")
public class Child {

    @Id
    @Column(name = "PARENT_ID")
    private Long parentId;

Now, when I run a JUnit repository test where I am trying to save a parent entity with a child entity, I get the exception:

org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): ...

What is the correct way of letting hibernate automatically set the Child.parentId to parent.id ?

I tried giving Child a Parent. But ran into other exceptions as Parent is not an Id.

UPDATE

I realised that the Child's Id is not a real primary key. It is just a mapping key. There can be several child entries for a parent.id.

Update

Now I start realising what I really need:

The child's primary key is a composite key out of three values: the parent id and two more String values.

@Entity
@Table(name = "CHILDREN")
public class Child {

    @Column(name = "PARENT_ID")
    private Long parentId;

    @Column(name = "PROPERTY_NAME")
    private String propertyName;

    @Column(name = "ANOTHER_PROPERTY")
    private String anotherProperty;

    @Column(name = "PROPERTY_VALUE")
    private String propertyValue;

So I need to map a composite key using parentId, properyName and anotherProperty. propertyValue is the actual value of that entry.

I think I might need to use IdClass or embeddedId. I tried, but without success so far.

1

There are 1 answers

3
Mark Adelsberger On

It may depend on your intended semantics, but if the child PK is also an FK to the Parent, then I would assume that represents an IS-A type relationship - or, in database terms, that CHILD is an extension table for PARENT. You could look at setting it up as table-per-class inheritance.

UPDATE

So based on your update, the ParentID in the Child is not the Child's PK; which means it should not be annotated with @Id and should just be set up like any other FK. I would consider not mapping ParentID but rather mapping Parent, though YMMV.

Then a separate question is, what (if anything - though if nothing, you're likely headed for trouble) is the unique ID of the Child? Is it an independently assigned surrogate? A composite that includes the Parent ID? Or something else? All of these cases can be accommodated, but without more information about which you need it's probably futile for me to elaborate each possibility...