CascadeType.MERGE in Bills may cause unnecessary ObjectOptimisticLockingFailureException
Description
Environment
causes
is blocked by
is caused by
Activity
Alessandro Domanico March 27, 2023 at 3:46 PM
The sub-task seems have simplified a lot the procedure, so also adding a few checks was easy.
Hope it helps!
Alessandro Domanico February 1, 2023 at 2:16 PM
Move to in order to do first
Alessandro Domanico February 1, 2023 at 2:13 PMEdited
Tried to find a way to implement all cases (there is also my second comment) but the class is too complex at the moment.
I think we need to first totally separate the gui from business logic, then try to customize the behavior.
This I think could be achieved with:
define initial local dataset, whether passed to the constructor (edit) or initialized (insert)
create all components and their listeners with
initComponents()
methodevery change should change immediately the local dataset within the action (and not just before saving)
save action requires confirmation and a confirmation is requested for changes upon close action
Then we can add the checks in my comments:
define initial local dataset, whether passed to the constructor (edit) or initialized (insert)
if editing, compare the local dataset with data from DB for changes since last time
create all components and their listeners with initComponents() method
every change should change immediately the local dataset within the action (and not just before saving)
save action requires confirmation and a confirmation is requested for changes upon close action
before saving re-check for changed data from DB in respect the current local dataset
Checks logic: the idea is to avoid unwanted changes for accounting purposes and to keep the informations aligned among different tables. I will analyse again and again all cases in order to simplify them as much as possible.
Alessandro Domanico January 18, 2023 at 10:36 AM
Rephrasing the whole discussion above, I think that we can simplify in this way:
insert a new Bill: the checkbill()
method is NEVER executed
edit an existing Bill: the checkbill()
method IS executed at the very BEGINNING
So far so good.
For this issue, I think we can just add the logic for the described cases in checkBill()
method, so it can be called at the beginning when edit, and just before save/paid for both edit and insert operations.
What do you think ?
Alessandro Domanico October 28, 2022 at 8:26 PM
Yes I know, I was the one adding that part in the latest developments… before was not there
The annotation
@ManyToOne(cascade = { CascadeType.MERGE})
in BIll, on relations Patient, Admission and PriceList causes their update at each Billsave()
, but this is not needed because the Bill never change their data. Moreover, those data may have been read from another module/feature and would be blocked without a necessary update.Solution: replace
@ManyToOne(cascade = { CascadeType.MERGE})
with just@ManyToOne
Instead, before to save the Bill (that could require some minutes, indeed), we could refresh the Admission and PriceList for changes in the DB.
Further improvement (nice to have): to perform a
EntityManager.refresh(object)
before thesave()
operation, with alerts to the user. Typically:PriceList changes (rarely changed) → could be changed the PriceList name (rare, showed in the Bill and persisted in BLL_LST_NAME), PriceList description (rare, not persisted in BILL), PriceList currency (very rare, showed aside the amounts)
Admission changes (frequently changed) → could be changed the Ward (rare, showed in the Bill), the status of the admission (very possible, discharged, showed in the Bill), the Admission ID (rare, the patient is discharged and readmitted while editing the Bill)
Patient changes (rarely changed) → could be changed the Patient name (very rare, showed in the Bill and persisted in BLL_PAT_NAME)