We ran across a problem where we have to maintain a date field - and preferably persist its value - where the date field is dependent on other entities' state. What is the correct way to address this problem with JPA2 + Hibernate + Spring?
Basically, we have three entities, let's call them Parent
, Child
, and Conf
. The dependentDate
is calculated by complex business rules that depend on other entities' state. Specifically, it should be Parent#date
minus Conf#delay
skipping all days that are weekends or holidays (persistent data).
The problem is that whenever the Parent#date
changes, all the children's dependentDate
s should be recalculated. This should happen also whenever the Child
object's conf
is changed. Currently, there is a service method for calculating the new date based on the Child
object's relations (let's call it calculateDate()
).
We are faced with the problem of where the field's value should be calculated. I came up with three possible solutions. Which of these - or possibly something else - is the preferred way of updating entities' fields that depend on other entities' state?
EntityListener
calculateDate()
methodThe following example shows the entity relations with omitted annotation configuration.
The entities
public class Parent {
LocalDate date;
Set<Child> children; // one-to-many
}
public class Conf {
int delay;
}
public class Child {
LocalDate dependentDate;
Conf conf; // many-to-one
Parent parent; // many-to-one
}
Complex business rules that depend on several entities' state belong to the service layer. There shouldn't be so many places in the application where the parent's date and the child's conf are changed, so you shouldn't have so many places where the new date calculation must be done.
If you really have so many places where this is done, you could make it clear that the date must be recomputed by passing a ChildDateUpdater instance (ChildDateUpdater being an interface) to the setter of the parent date and the setter of the child conf. This would make it obvious that something must be done every time these two fields are changed:
In Parent:
public void setDate(Date date, ChildDateUpdater childDateUpdater) {
this.date = date;
for (Child child : children) {
childDateUpdater.updateChildDate(child);
}
}
In Child:
public void setConf(Conf conf, ChildDateUpdater childDateUpdater) {
this.conf = conf;
childDateUpdater.updateChildDate(this);
}
Encapsulate your data access in a DAO. When a Parent
is going to be saved, check if there has been any changes to its values and, if so, update the children accordingly.
The trigger option of realsim
is also feasible (basically it is the same idea implemented at a different level) but then you would lose portability (and also there will be the issue with instances of Children already loaded not being updated).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.