Thursday, March 28, 2013

Hibernate collection mapping - inverse="true"

Following image describe simple one to many bidirectional entity mapping
There is Entity Author that have collection of written books.
Relation ship attribute 'inverse' means direction of relation. 'true' say that relation begin at Author's object at collection or many side or relation. Otherwise default value 'false' say that relation starts at one side of relation.

inverse="true"

When inverse is set to 'true' following code will create and persist new book.
Book book = new Book();
author.getBooks().add(book);
save(author);

inverse="false"

Same code from previous example will lead to exception
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Author
 at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:219)
 at org.hibernate.type.EntityType.getIdentifier(EntityType.java:108)
If it should work there have to be extra call for saving of Book instance.
Inverse could appear in case on unidirectional and bidirectional relation. Inverse could be used for all types of collection mapping types.

Object and mapping example details

Author and Book Java object could look like:
public class Author {

    private Integer id;

    private String name;

    private Set<Book> books;

    /**
     * @return the books
     */
    public Set<Book> getBooks() {
        return books;
    }

    /**
     * @param books the books to set
     */
    public void setBooks(Set<Book> books) {
        this.books = books;
    }


   ...

}
Book object could look like:
public class Book {

    private Integer id;
    
    private String name;
    
    private String description;
    
    ...
}
And relation mapping between this two object in Author mapping file usually Author.hbm.xml:
 <set name="books" inverse="true">
  <key column="id_author" not-null="true" foreign-key="book_author"/>
  <one-to-many class="Book" />
 </set>
When it's mapped as bidirectional relation there should be in Book mapping file Book.hbm.xml:
<many-to-one name="author" class="Author" column="id_author" foreign-key="book_author" not-null="true"/>