When defining your objects to be persisted and the relationships between them, it is often required to define dependencies between these related objects. When persisting an object should we also persist any related objects? What should happen to a related object when an object is deleted ? Can the related object exist in its own right beyond the lifecycle of the other object, or should it be deleted along with the other object ? This behaviour can be defined with JPA and with DataNucleus. Lets take an example
@Entity public class Owner { @OneToOne private DrivingLicense license; @OneToMany(mappedBy="owner") private Collection cars; ... } @Entity public class DrivingLicense { private String serialNumber; ... } @Entity public class Car { private String registrationNumber; @ManyToOne private Owner owner; ... }
So we have an Owner of a collection of vintage Car's, and the Owner has a DrivingLicense. We want to define lifecycle dependencies to match the relationships that we have between these objects. So in our example what we are going to do is
So we update our class to reflect this
@Entity public class Owner { @OneToOne(cascade=CascadeType.ALL) private DrivingLicense license; @OneToMany(mappedBy="owner", cascade={CascadeType.PERSIST, CascadeType.MERGE}) private Collection cars; ... } @Entity public class DrivingLicense { private String serialNumber; ... } @Entity public class Car { private String registrationNumber; @ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE}) private Owner owner; ... }
So we make use of the cascade attribute of the relation annotations. We could express this similarly in XML
<entity-mappings> <entity class="mydomain.Owner"> <attributes> <one-to-many name="cars"> <cascade> <cascade-persist/> <cascade-merge/> </cascade> </one-to-many> <one-to-one name="license"> <cascade> <cascade-all/> </cascade> </one-to-one> ... </attributes> </entity> <entity class="mydomain.DrivingLicense"> ... </entity> <entity class="mydomain.Car"> <attributes> <many-to-one name="owner"> <cascade> <cascade-persist/> <cascade-merge/> </cascade> </many-to-one> ... </attributes> </entity> </entity-mappings>
When an element is removed from a collection, or when a 1-1 relation is nulled, sometimes it is desirable to delete the other object. JPA2 defines a facility of removing "orphans" by specifying metadata for a 1-1 or 1-N relation. Let's take an example. In the above relation between Owner and DrivingLicense if we set the owners license field to null, this should mean that the license is deleted. So we could change it to be
@Entity public class Owner { @OneToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval=true) private DrivingLicense license; ... } @Entity public class DrivingLicense { private String serialNumber; ... }
So from now on, if we delete the Owner we delete the DrivingLicense, and if we set the license field of DrivingLicense to null then we also delete the DrivingLicense.