How do I update an attribute in Parent entity once children records have been modified ?
I have a parent entity named “Job” which has ONE_TO_MANY link to child entity named “JobStatusHistory”.
JobStatusHistory keeps track of all the times a job has had it’s status changed.
All the fields are stored in the database.
In the Job entity, “currentJobStatus” should always be the status value of the most recent (latest date) JobStatusHistory record associated with the Job.
I already created a function in JobServiceBean to return the latest Job status for a job…so that part is working
But I am having serious difficulty in updating the particular Job record with the latest status and committing it to the database.
I have one screen “job-edit.xml” that edits the Job and has a nested table of related JobStatusHistory records.
Once there is a CRUD operation on items in the nested table, the “currentJobStatus” attribute should be updated in the Job entity and persisted to the database.
Please suggest the best approach and what events should I rely on.
I have tried using “aftercommit” within JobStatusHistoryEntityListener but getting an error that Job has been updated by another transaction.
I have tried so many things but not getting it to work. Please see my approache below and tell me if I am on the right track :
Job entity:
jobNo
clientName
currentJobStatus (type: jobStatus)
JobStatusHistory entity:
job (type: Job)
date
jobStatus (type: jobStatus)
JobStatus:
name
JobStatusHistoryEntityListener :
package com.company.lms.listener;
import com.company.lms.entity.Job;
import com.company.lms.entity.JobStatusHistory;
import com.company.lms.service.JobService;
import com.haulmont.cuba.core.EntityManager;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.Query;
import com.haulmont.cuba.core.Transaction;
import com.haulmont.cuba.core.entity.contracts.Id;
import com.haulmont.cuba.core.global.DataManager;
import com.haulmont.cuba.core.listener.BeforeDeleteEntityListener;
import com.haulmont.cuba.core.listener.BeforeInsertEntityListener;
import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.inject.Inject;
import java.sql.Connection;
@Component(JobStatusHistoryEntityListener.NAME)
public class JobStatusHistoryEntityListener
implements BeforeInsertEntityListener<JobStatusHistory>,
BeforeUpdateEntityListener<JobStatusHistory>,
BeforeDeleteEntityListener<JobStatusHistory>
{
public static final String NAME = "lms_JobStatusHistoryEntityListener";
@Inject
private JobService jobService;
@Inject
private DataManager dataManager;
@Inject
private Persistence persistence;
@Override
public void onBeforeDelete(JobStatusHistory entity, EntityManager entityManager) {
updateJobStatus(entity.getJob());
}
@Override
public void onBeforeInsert(JobStatusHistory entity, EntityManager entityManager) {
updateJobStatus(entity.getJob());
}
@Override
public void onBeforeUpdate(JobStatusHistory entity, EntityManager entityManager) {
updateJobStatus(entity.getJob());
}
// We need to update jobStatus field in Job entity but have to do so after successful transaction commit
private void updateJobStatus(Job job) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
job.setCurrentJobStatus(jobService.getJobCurrentStatus(job));
dataManager.commit(job);
}
});
}
}