Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Atomic Operation is failing to update child entities with FK integrity constraint violation #3322

Open
Abhijit-2025 opened this issue Feb 16, 2025 · 1 comment

Comments

@Abhijit-2025
Copy link

I have following 2 entities where in database decision's ID is a FK in legal table.

package com.example.app.model;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Setter
public class Decision {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String type;
    private String outcome;

    @OneToMany(mappedBy = "decision", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Legal> legalList = new ArrayList<>();

}

and

package com.example.app.model;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
public class Legal {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToOne
    @JoinColumn(name = "decision_id", nullable = false)
    private Decision decision;
}

Since I want to use atomic operation to update decision along with list of associated legal lists, I tried the following sample request but its failing saying integrity constraint violated FK - parent key not found.

{
  "atomic:operations": [
    {
      "op": "add",
      "data": {
        "type": "decision",
        "lid": "temp-decision-1",
        "attributes": {
          "type": "Court Decision",
          "outcome": "Approved"
        }
      }
    },
    {
      "op": "add",
      "data": {
        "type": "legal",
        "attributes": {
          "name": "Legal Document 1"
        },
        "relationships": {
          "decision": {
            "data": {
              "type": "decision",
              "id": "temp-decision-1"
            }
          }
        }
      }
    }
  ]
}

I am getting Database Error - integrity constraint violated - parent key not found.

Observations
• Issue with Foreign Key Constraint:
• It seems that Elide replaces the client-generated ID (temp-decision-1) with an auto-generated ID while persisting Decision.
• When it attempts to insert Legal, it fails because the referenced decision_id (temp-decision-1) is not found in the database.
• Possible Root Cause:
• Elide might be executing both operations simultaneously instead of ensuring Decision is persisted first and then inserting Legal.
• Since Decision.id is auto-generated, Elide cannot resolve the temporary ID correctly before Legal is inserted.

Expected Behavior
• The Decision should be persisted first, generating a valid id.
• The Legal entity should then reference the newly created Decision using the correct id.
• The entire request should execute atomically, ensuring all operations succeed or fail together.

Questions
1. Does Elide guarantee sequential execution in atomic operations (ensuring Decision is persisted first before inserting Legal)?
2. How can I ensure that Legal correctly references the generated Decision.id instead of a temporary client-assigned ID?
3. Is there an alternative way to enforce foreign key constraints while using Atomic Operations in Elide?

Environment Details
• Elide Version: 7.1.4
• Database Used: Oracle
• Spring Boot Version: 3.3.7

@justin-tay
Copy link
Collaborator

Can't replicate this. In fact I get an error given your input as the id for Legal is not set. That said I don't have Oracle to test.

Given

{
  "atomic:operations": [
    {
      "op": "add",
      "data": {
        "type": "decision",
        "id": "temp-decision-1",
        "attributes": {
          "type": "Court Decision",
          "outcome": "Approved"
        }
      }
    },
    {
      "op": "add",
      "data": {
        "type": "legal",
        "id": "moo",
        "attributes": {
          "name": "Legal Document 1"
        },
        "relationships": {
          "decision": {
            "data": {
              "type": "decision",
              "id": "temp-decision-1"
            }
          }
        }
      }
    }
  ]
}

The logs show

19-02-2025 21:13:30.169 �[35m[task-1]�[0;39m [Elide, ] �[39mDEBUG�[0;39m org.hibernate.SQL.logStatement - insert into Decision (outcome,type,id) values (?,?,default)
Hibernate: insert into Decision (outcome,type,id) values (?,?,default)
19-02-2025 21:13:30.201 �[35m[task-1]�[0;39m [Elide, ] �[39mDEBUG�[0;39m org.hibernate.SQL.logStatement - insert into Legal (decision_id,name,id) values (?,?,default)
Hibernate: insert into Legal (decision_id,name,id) values (?,?,default)

The output is

{
  "atomic:results": [
    {
      "data": {
        "type": "decision",
        "id": "1",
        "attributes": {
          "outcome": "Approved",
          "type": "Court Decision"
        },
        "relationships": {
          "legalList": {
            "data": [
              {
                "type": "legal",
                "id": "1"
              }
            ]
          }
        }
      }
    },
    {
      "data": {
        "type": "legal",
        "id": "1",
        "attributes": {
          "name": "Legal Document 1"
        },
        "relationships": {
          "decision": {
            "data": {
              "type": "decision",
              "id": "1"
            }
          }
        }
      }
    }
  ]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants