I'm having a bit of trouble mapping the following:
public class Operation {
private Integer id;
private String name;
private List<Item> items = new ArrayList<Item>();
//set/getters/hashcode/etc. omitted
public void addItem(Item i,Operation end) {
i.setOperationStart(this);
i.setOperationEnd(end};
items.add(i);
end.getItems().add(i);
}
public class Item {
private Integer id;
private String name;
private Operation operationStart;
private Operation operationEnd;
//set/getters/hashcode/etc. omitted
}
So basically an Operation have a bunch of Items, and an Item belongs to 2 Operations. Also, it doesn't make sense for an item to exist if one of the Operations doesn't exist, i.e. if I delete one of the Operations, I want to remove the item from wherever else it's stored as well.
Does anyone have a pointer on how I'd map the above classes, or could point me to some examples showing how to map a child object that has 2 parents ?
From an object oriented point of view what is represented looks like two ManyToOne
associations between Item
and Operation
, one of them being bidirectional. This could be mapped like this:
@Entity
public class Item {
@Id private Integer id;
private String name;
@ManyToOne
private Operation operationStart;
@ManyToOne
private Operation operationEnd;
//set/getters/hashcode/etc. omitted
}
@Entity
public class Operation {
@Id private Integer id;
private String name;
@OneToMany(cascade = CascadeType.REMOVE, mappedBy="operationStart")
private List<Item> items = new ArrayList<Item>();
//set/getters/hashcode/etc. omitted
}
This should result in an [ITEM]
table having two FKs pointing on [OPERATION]
. And populating the items
collection would result in a SELECT
restricted to one of them (the ID
of the start operation in the above example).
I don't know if this scenario makes sense but this is IMO the only scenario Hibernate can handle. If this is not what you want, then I think you should have two collections on the Operation
side (that you could maybe hide behind friendly methods).
Whether you use hbm.xml or annotations doesn't make any difference.
This sounds like a combination of a many-to-many relation between Items and Operations, and a ternary relation between one Item and two Operations.
Assuming that your business logic is fixed on exactly two Operations per Item, and not more than that, I'd tackle this problem as follows:
The tricky part, as you said, is when you delete an operation. Whether you use an intermediate object or not, you need to cascade the delete to the list with all-delete-orphan. However, I suspect that you'll have some issues due to 2nd level cache. The only way I know around that is this:
op1
, traverse the object graph and detach each intermediate object from its other operation op2
, and only then flush. Otherwise hibernate will refuse to delete the intermediate objects because they are still held in some sets in other Operations.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With