Can't insert ManyToOne with Join Table

Hey, I have a OneToMany/ManyToOne relationship which uses a join table. The reason it uses a join table as opposed to just a mapped by/join column is because the ID of the entity with the many to one relationship is used throughout the database for other things. I should be able to create DerpTwo without any DerpOne’s and vice versa. Initially a DerpTwo can either be registered without a DerpOne, or the registration is attributed to a DerpOne. Should the attribution happen, the derp_two_id in the join table can be used to join on other tables (f.ex “Purchase”, which would then also have a derp_two_id).

For some reason I don’t understand, it will not let me create a derpTwo without a derpOne even if it should allow nullables in all directions. If the type of derpTwo’s is set to Set, it gives me this error:

not-null property references a null or transient value : com.safetywing.insurance.domain.models.rh.DerpTwo.derpOne.

If I make it a list it doesn’t throw an exception on the insert, but the DerpTwo is just not persisted.

DerpOne

    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "derp")
    private String derp;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "DerpOne_DerpTwo",
        joinColumns = { @JoinColumn(name = "derp_one_id") },
        inverseJoinColumns = { @JoinColumn(name = "derp_two_id", referencedColumnName = "id") })
    private Set<DerpTwo> derpTwos;

DerpTwo

    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "derp")
    private String derp;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinTable(
        name = "DerpOne_DerpTwo",
        joinColumns = { @JoinColumn(name = "derp_two_id") },
        inverseJoinColumns = { @JoinColumn(name = "derp_one_id", referencedColumnName = "id") })
    private DerpOne derpOne;

It’s a Liquibase Schema but should be pretty self explanatory:

  <changeSet author="earl" id="create-derp-table">
        <createTable tableName="DerpOne">
            <column name="id" type="BIGINT">
                <constraints primaryKey="true"/>
            </column>
            <column name="derp" type="VARCHAR(255)"/>
        </createTable>
        <createTable tableName="DerpTwo">
            <column name="id" type="BIGINT">
                <constraints primaryKey="true"/>
            </column>
            <column name="derp" type="VARCHAR(255)"/>
        </createTable>
    </changeSet>

    <changeSet id="create-derp-join-table" author="earl">
        <createTable tableName="DerpOne_DerpTwo">
            <column name="derp_one_id" type="BIGINT">
            </column>
            <column name="derp_two_id" type="BIGINT"/>
        </createTable>
    </changeSet>

Code to insert

        EntityManager em = entityManagerProvider.get();
        DerpTwo derpTwo = new DerpTwo();
        derpTwo.setDerp("Derp");
        derpTwo.setId(1L);
        em.persist(derpTwo);

Any help much appreciated, thanks!

Use Cascade.PERSIST on relation.
It’s interesting note the following , to have a onetomany relation.
you must have the owner of the onemany relation be persisted first of the owner of the manyone relation. but if none exist you just need to persist the manyone entity with cascade persist defined on relation.

Its also not quite common you have objects of such kind, both objects seem to be of same class of “something” and since they are form “same sort of class” i dont see how one object owns many over other… unless in a true child-parent relationship.

Use also “mappedby” to avoid redeclare the join table.