The above entities all inherits from StandardEntity and therefore have SafeDelete interface. I would like to offer the possibility to permanently delete selected companies from the UI.
Question 1:
So the issue is the following, when I disable SoftDelete and delete a Company I get the problem of foreign key violation that I have in the Contract (references back the company).
Question 2:
I am wondering how one should delete objects when disabling SoftDelete. Do I need to add every related entity to the CommitContext (e.g. all the Contract entities of the Company I would like to delete)? Or is it sufficient to just remove the Company and the hope the annotation @OnDelete(DeletePolicy.CASCADE) will do that?
I wrote an integration test (MyIntegrationTest.java) to reproduce the problem. Please find attached the test project.
Well, now you should feel what Soft Deletion CUBA’s feature brings to you! It’s the ability for alive object to reference a hidden (soft-deleted) object in the database. It’s not available in standard JPA frameworks.
When not using soft deletion, you need to decide for each foreign key constraint: what on-delete rule to use for it.
There are many resources in the internet about foreign key constraints, e.g.:
Main rules are:
cascade (automatically delete Contract when associated Company is deleted)
set null or “unlink” (automatically clear linkfrom Contract to Company when Company is deleted)
restrict - default behavior, throws an error
It does make sense to set @OnDeleteInverse annotations on Many-to-one association fields between non-soft-deleted entities.
Studio will adjust foreign key constraint definitions based on these annotations.
E.g. if you have such source code:
@Table(name = "PLAYGROUND_COMPANY")
@Entity(name = "playground_Company")
public class Company extends BaseUuidEntity {
...
}
@Table(name = "PLAYGROUND_CONTRACT")
@Entity(name = "playground_Contract")
@NamePattern("%s|name")
public class Contract extends BaseUuidEntity {
@OnDeleteInverse(DeletePolicy.UNLINK)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "COMPANY_ID")
private Company company;
// ...
}
Then Studio will generate foreign key constraint with “set null” on-delete mode:
alter table PLAYGROUND_CONTRACT
add constraint FK_PLAYGROUND_CONTRACT_ON_COMPANY
foreign key (COMPANY_ID) references PLAYGROUND_COMPANY(ID)
on delete SET NULL^
The same with Cascade policy:
@OnDeleteInverse(DeletePolicy.CASCADE)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "COMPANY_ID")
private Company company;
-->
alter table PLAYGROUND_CONTRACT
add constraint FK_PLAYGROUND_CONTRACT_ON_COMPANY
foreign key (COMPANY_ID) references PLAYGROUND_COMPANY(ID)
on delete CASCADE;
For the first response: I understand that the SoftDelete is rather a design pattern than a feature to deal with database potential inconsistencies due to deleting referenced records. My question is maybe not precise. By disabling SoftDelete, I mean I have the ability at runtime to do something like this:
CommitContext ccDelete = new CommitContext();
ccDelete.setSoftDeletion(false);
ccDelete.addInstanceToRemove(company);
dataManager.commit(ccDelete);
The above snippet is what I provided in the integration test of test project attached above. Do I really need to make Company and Contract inherit from BaseUuidEntity? Wouldn’t be possible to make the code above work with inheritance from StandardEntity?
No, you don’t need them to inherit from BaseUuidEntity. It was just a sample.
If you inherit from StandardEntity - then the entity becomes soft-deleted, because StandardEntity already implements SoftDelete interface and contains DELETE_TS column.
The snippet above will work, but you need to think about all foreign key references from other entities to the entity you are deleting.
It’s not CUBA specifics. These decisions have to be made for any application working with SQL databases, because foreign key constraints are part of SQL standard.
regarding this, I am trying to remove SoftDelete from my entities, and I would like to create a class that extends BaseUuidEntity just like StandardEntity do. I want this class to implement all interfaces but SoftDelete.
This is my class:
@ MappedSuperclass
@ MetaClass(name = “myClassEntity”)
@ UnavailableInSecurityConstraints
public class MyClassEntity extends BaseUuidEntity implements Versioned, Creatable, Updatable { …
But when I try to run I have this error:
=================================================================
Problems with entity enhancement detected:
Entity class MyClassEntity is missing some of enhancing interfaces: CubaEnhanced; PersistenceObject; PersistenceWeaved; PersistenceWeavedFetchGroups;
OK Thank you for your fast rensponse! I should explain better because I don’t want this class to be persistent.
I want a superclass that my N entities can extend, in place of the StandardEntity, with all the features of StandardEntity but without SoftDelete.
as is:
my N persistent entities —> StandardEntity (with s/d) —> BaseUuidEntity
desired:
my N persistent entities —> MyClassEntity (without s/d) —> BaseUuidEntity
Another soultion that works is to extend directly BaseUuidEntity, but I should declare every time all the filelds such as CREATED_BY, UPDATED_BY
If I would be able to create MyClassEntity instead I could declare all the filelds such as CREATED_BY, UPDATED_BY only one time, and my entities will extend that.