Friday, February 27, 2015

Hibernate's inverse=true on sets, and cascade=all

review this example: http://www.mkyong.com/hibernate/inverse-true-example-and-explanation/

upshot: makes more sense to do inverse=true -- results in fewer SQL statements.

But what if you just want a many-to-one relationship? e.g. a Rectangle that has a instance variable of type Point and Point can be a property of multiple Rectangles. Furthermore, you only need this to be unidirectional. No need to navigate from Point to Rectangles. (Note: a rectangle's location be defined by a single point.) In this case inverse="true" won't help because it can only be applied to a collection not a property. So what if you want to persist the Rectangle with one Hibernate save statement, and not have to first save the point, then save the rectangle to avoid a referential integrity error. The trick was mentioned in passing here: using cascade="all" on the many-to-one element in the unidirectional relationship's only side, in this case Rectangle, or if using annotations @ManyToOne(cascade=CascadeType.ALL) -- with cascade set to all, " if we perform an insert on the child row, Hibernate will automatically create the parent row based on where the child row is pointing." THAT saves a line of code, which can be a HUGE benefit especially if this is a polymorphic Hibernate util, otherwise, you would have to do something like either cast the entity to see if it's a Rectangle and has a point or in which case persist the Point or create a "performPreSave(session)" which is called on all entities where a Rectangle could override and persist its Point. Hacky! So...use cascade="all"...

Update. Rather than cascade="all" to achieve this single-save-cascade effect, should use "save-update" because you don't want to cascade a delete probably ever, if it's a many-to-one, since there could be other shapes like polygon relating to that point and possibly even other rectangles. In fact, cascade delete would probably only ever make sense in a one-to-one, and only ever in a one-to-many if the many-side table (the table holding the foreign key to the one-side table) did not contain foreign key references / relations to other entities. Answer here referencing Hibernate docs agrees with this.

This save-update effect would be useful to the afore-mentioned unidirectional relationship for the purposes of adding the related records upon saving the primary record, in this case the rectangle.