Skip to content

InsertOptions.ON_CONFLICT_NOTHING with cascade #3712

@dragkes

Description

@dragkes

When inserting an entity with InsertOptions.ON_CONFLICT_NOTHING, the root entity is correctly skipped on conflict, but the ORM still performs cascading inserts on its child entities. This results in a foreign key violation because the parent object was never inserted.

Example

@Entity
public class TestOne extends Model {

    @Id
    private String id;

    @Column(unique = true)
    private String otherUnique;

    @OneToMany(mappedBy = "testOne", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<TestTwo> testTwos = new ArrayList<>();

    public TestOne(String id, String otherUnique) {
        this.id = id;
        this.otherUnique = otherUnique;
    }

    public String getId() { return id; }
    public List<TestTwo> getTestTwos() { return testTwos; }
    public void setTestTwos(List<TestTwo> testTwos) { this.testTwos = testTwos; }
}

@Entity
public class TestTwo extends Model {

    @Id
    private String id;

    @ManyToOne
    @JoinColumn
    private TestOne testOne;

    public TestTwo(String id) { this.id = id; }

    public String getId() { return id; }
    public TestOne getTestOne() { return testOne; }
    public void setTestOne(TestOne testOne) { this.testOne = testOne; }
}

class CascadeTest {

    @Test
    void cascade() {
        Database db = DB.getDefault();

        TestOne testOne1 = new TestOne("testOne1", "unique");
        testOne1.insert(); // success

        TestOne testOne2 = new TestOne("testOne2", "unique");
        TestTwo testTwo1 = new TestTwo("testTwo21");
        testTwo1.setTestOne(testOne2);
        testOne2.getTestTwos().add(testTwo1);

        db.insert(testOne2, InsertOptions.ON_CONFLICT_NOTHING); // fail
    }
}

Observed Behavior

The ORM still attempts to cascade and insert testTwo1, causing:

DataIntegrity Error when batch flush on sql: insert into test_two (id, test_one_id) values (?,?)
#1: ERROR: insert or update on table "test_two" violates foreign key constraint "fk_test_two_test_one_id"
Detail: Key (test_one_id)=(testOne2) is not present in table "test_one"

Expected Behavior

If the parent insert is skipped due to a conflict (e.g., because of ON_CONFLICT_NOTHING), then cascading should not occur probably?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions