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.