Home > Mobile >  Cascade Delete in JPA Failing
Cascade Delete in JPA Failing

Time:10-25

I am using Java, Spring and JPA and cannot get cascade deletion to work.

I have a class Tenant that looks like this

@Entity
@Validated
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TenantConstraints
public class Tenant {

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tenant_gen")
  @SequenceGenerator(name="tenant_gen", sequenceName="tenant_seq", allocationSize=1)
  @JsonProperty("id")
  private Long id = null;

  @JsonIgnore
  @OneToMany(mappedBy = "tenant", fetch = FetchType.EAGER)
  private List<DeploymentStep> deploymentSteps = new ArrayList();

  ...
}

My DeploymentStep class looks like this:

@Entity
@Validated
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DeploymentStep   {
  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "deployment_step_gen")
  @SequenceGenerator(name="deployment_step_gen", sequenceName="deployment_step_seq", allocationSize=1)
  @JsonProperty("id")
  private Long id = null;
 
  @ManyToOne(cascade = CascadeType.ALL)
  @JsonIgnore
  private Tenant tenant = null;

  ...
}

I have a repository class that looks like this

public interface TenantRepository extends JpaRepository<Tenant, Long> {
   ...
}

When I call the built-in delete method on this repository like so tenantRepository.delete(tenantId) and I have deployment steps for the particular tenant I'm deleting, the delete fails.

In my postgres database I have a cascade constraint set

ALTER TABLE public.deployment_step
  DROP CONSTRAINT tenant_fkey
, ADD  CONSTRAINT tenant_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenant(id) ON DELETE CASCADE;

When I delete the tenant that has deployment steps using a database query manually, the tenant and all deploymentsteps get deleted without any issue.

What am I doing wrong in the code?

CodePudding user response:

You have the cascade in DeploymentStep but you are deleting the Tenant. To delete the DeploymentStep using the TenantRepository you should put the cascade in the Tenant entity.

@Entity
@Validated
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TenantConstraints
public class Tenant {

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tenant_gen")
  @SequenceGenerator(name="tenant_gen", sequenceName="tenant_seq", allocationSize=1)
  @JsonProperty("id")
  private Long id = null;

  @JsonIgnore
  @OneToMany(mappedBy = "tenant", fetch = FetchType.EAGER,cascade = CascadeType.ALL)
  private List<DeploymentStep> deploymentSteps = new ArrayList();

  ...
}

CodePudding user response:

The tenants many-side is wrong, it misses the cascade-specification.

https://docs.oracle.com/javaee/6/api/javax/persistence/OneToMany.html#cascade()

Defaults to no operations being cascaded.

JPA did not expect the DeploymentSteps to disappear and rollback the transaction.

  • Related