views:

237

answers:

2

Supposing I have two entities a parent object and a child. I want the child to have a relationship specified to the parent entity and a reference, but I don't want the parent to have to know about it. The reason for this is there are numerous such relationships and explicitly specifying the relationship for all these children will mean continually updating and polluting the parent objects. However I still want deletes of the parent object to cascade to the child. As an additional constraint the child object only ever has the reference to the parent entity set by setting an attribute that references the parent's ID. Supposing I have something like:

@Entity
class Child {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    @Column(nullable=false)
    private Long parentId;

    @ManyToOne(fetch=FetchType.LAZY, optional=false)
    @JoinColumn(name="parentId", insertable=false, updatable=false, nullable=false, unique=false)
    private Parent parentEntity;

    // etc...

}

@Entity
class Parent {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    // etc...   
}

Then is there any way that deletes of the parent object can be cascaded to the child without adding an additional relationship to the parent entity?

A solution that uses only JPA annotations would be preferred, but any help would be appreciated.

+2  A: 

No it's not possible.

Cascades (of any kind) traverse relationships. If you don't tell JPA about the relationship from A to B (even if there is one from B to A) then it can't automatically traverse it.

On a side note: only specifying the parent ID rather than the parent entity is going to make it even more difficult. Either Hibernate/JPA isn't the right tool for what you're doing or you need to embrace how it works, meaning specifying and maintaining object relationships.

cletus
+1  A: 

Adding the parentId instead of the parent directly makes your life way harder. Hibernate is only saving an id in the database. So whats your point of doing it yourself? Back to your problem. You have to make the relationship bidirectional and add cascade=CascadeType.ALL to your children attribute which itself is mappedBy="parent". It's small, it's easy, it's fast.

Willi
At the point this object is created I only have the parent Id (it came via an RPC call), so it is convenient just to add that rather than do another lookup.
Dean Povey
You can use session.load(Parent.class, parentId) which will create a placeholder you can use in your statement without actually querying the database.
Willi