I have a one-to-many bi-directional relationship.
0 or 1 customer ↔ List of 0 or more product orders .
This relationship must be set or canceled for both objects: On the client side, I want to establish a list of product orders assigned to the client; The client must be installed / disabled for the selected orders automatically. On the product ordering side, I want to install a client who is assigned another; this product order must then be removed from its previously configured customer list and added to the new assigned customer list.
I want to use pure JPA 2.0 annotations and a single merge call only to the entity manager (with cascading options). I tried with the following code snippets but it does not work (I use EclipseLink 2.2.0 as a continuity provider)
@Entity
public class Client implements Serializable {
@OneToMany(mappedBy = "client", cascade= CascadeType.ALL)
private List<ProductOrder> orders = new ArrayList<>();
public void setOrders(List<ProductOrder> orders) {
for (ProductOrder order : this.orders) {
order.unsetClient();
}
for (ProductOrder order : orders) {
order.setClient(this);
}
this.orders = orders;
}
}
@Entity
public class ProductOrder implements Serializable {
@ManyToOne(cascade= CascadeType.ALL)
private Client client;
public void setClient(Client client) {
if (this.client != null) {
this.client.getOrders().remove(this);
}
this.client = client;
if (client != null && !client.getOrders().contains(this)) {
client.getOrders().add(this);
}
}
public void unsetClient() {
client = null;
}
}
Facade code for persisting client:
// call setters on entity by JSF frontend...
getEntityManager().merge(client)
Facade Code for Pending Product Order:
// call setters on entity by JSF frontend...
getEntityManager().merge(productOrder)
When changing the destination of the client on the order side, it works well: on the client side, the order is deleted from the previous customer list and added to the new customer list (if it is redefined).
( , ), , ( , - .
, " " . , ( ), Client # setOrders. ?
EDIT: , , . . :
("" / "" ) , .
@Entity
public class Client implements Serializable, EntityContainer {
@OneToMany(mappedBy = "client", cascade= CascadeType.ALL)
private List<ProductOrder> orders = new ArrayList<>();
@Transient
private List<ProductOrder> modifiedOrders = new ArrayList<>();
public void setOrders(List<ProductOrder> orders) {
if (orders == null) {
orders = new ArrayList<>();
}
modifiedOrders = new ArrayList<>();
for (ProductOrder order : this.orders) {
order.unsetClient();
modifiedOrders.add(order);
}
for (ProductOrder order : orders) {
order.setClient(this);
modifiedOrders.add(order);
}
this.orders = orders;
}
@Override
public List getContainedEntities() {
return modifiedOrders;
}
, , , - , . , , .
// call setters on entity by JSF frontend...
getEntityManager().merge(entity);
if (entity instanceof EntityContainer) {
EntityContainer entityContainer = (EntityContainer) entity;
for (Object childEntity : entityContainer.getContainedEntities()) {
getEntityManager().merge(childEntity);
}
}