Hibernate Tutorial 04

|
All materials on our website are shared by users. If you have any questions about copyright issues, please report us to resolve them. We are always happy to assist you.
 47 views
of 10

Please download to get full document.

View again

Description
Hibernate Tutorial 04 Many-to-one and One-to-one Association By Gary Mak hibernatetutorials@metaarchit.com September 2006 1. Many-to-one association In our online bookshop application, each book is related to one publisher while one publisher may publish many books. The association from book to publisher is called a “many-to-one” association. As this association is navigable from book to publisher only, it is also a kind of “unidirectional” association. Otherwise, if the association is naviga
Share
Tags
Transcript
  Page 1 of 10 Hibernate Tutorial 04 Many-to-one and One-to-oneAssociation By Gary Mak hibernatetutorials@metaarchit.com September 2006 1. Many-to-one association In our online bookshop application, each book is related to one publisher while one publisher maypublish many books. The association from book to publisher is called a “many-to-one” association.As this association is navigable from book to publisher only, it is also a kind of “unidirectional”association. Otherwise, if the association is navigable in both directions (i.e. from book to publisherand from publisher to book), it will be a “bi-directional” association.Remember that we have a Publisher class in our application that hasn’t mapped to the database.Following the best practice of object identifier discussed in last chapter, we should add anauto-generated id property on it. public class Publisher {  private Long id; private String code;private String name;private String address;// Getters and Setters}<hibernate-mapping package= com.metaarchit.bookshop ><class name= Publisher table= PUBLISHER ><id name= id type= long column= ID ><generator class= native /></id><property name= code type= string ><column name= CODE length= 4 not-null= true unique= true /></property><property name= name type= string ><column name= PUBLISHER_NAME length= 100 not-null= true /></property><property name= address type= string ><column name= ADDRESS length= 200 /></property></class></hibernate-mapping>  Page 2 of 10 For we have added a new persistent object to our application, we need to specify it in the Hibernateconfiguration file also. <mapping resource= com/metaarchit/bookshop/Publisher.hbm.xml /> For our Book class, we already have a publisher property which type is Publisher. It is not used inthe previous examples. public class Book {private Long id;private String isbn;private String name;  private Publisher publisher; private Date publishDate;private Integer price;private List chapters;// Getters and Setters} To make use of this property, we can add a <many-to-one> mapping to the mapping definition of Book class. This will add a column PUBLISHER_ID in the BOOK table and store the ID of associated publisher. Don’t forget to run the schema update task for reflecting the changes todatabase. <hibernate-mapping package= com.metaarchit.bookshop ><class name= Book table= BOOK ><id name= id type= long column= ID ><generator class= native /></id><property name= isbn type= string ><column name= ISBN length= 50 not-null= true unique= true /></property><property name= name type= string ><column name= BOOK_NAME length= 100 not-null= true /></property><property name= publishDate type= date column= PUBLISH_DATE /><property name= price type= int column= PRICE /> <many-to-one name= publisher class= Publisher column= PUBLISHER_ID /> </class></hibernate-mapping> 1.1.   Lazy initialization Suppose we have a method for retrieving a book object given its ID. For we have added the  Page 3 of 10 <many-to-one> mapping, the publisher object related to the book should also be retrieved at thesame time. Session session = factory.openSession();try {Book book = (Book) session.get(Book.class, id);return book;} finally {session.close();} But when we access the publisher object through book.getPublisher() outside this method, anexception will occur. System.out.println(book.getName());System.out.println(book.getPublisher().getName()); If we put the access code inside the try block of the method body, everything is OK. What’s thereason for this exception? It is because Hibernate will not load our publisher object from databaseuntil the first access. In Hibernate, this is called “lazy initialization” which can avoid unnecessarydatabase queries and thus enhance the performance. Since the publisher is first accessed outside thesession (which has been closed), an exception was thrown.If we want the publisher object can be accessed outside the session, there will be two possiblesolutions. One is to initialize the publisher explicitly, we can call the method Hibernate.initialize()for this task. This will force the publisher object to be loaded from database. Session session = factory.openSession();try {Book book = (Book) session.get(Book.class, id); Hibernate.initialize(book.getPublisher()); return book;} finally {session.close();} Another solution is to turn off the lazy initialization feature for this association. This may decreasethe performance as the publisher object will be loaded together with the book object every time. <hibernate-mapping package= com.metaarchit.bookshop ><class name= Book table= BOOK >...<many-to-one name= publisher class= Publisher column= PUBLISHER_ID lazy= false /></class></hibernate-mapping>  Page 4 of 10 1.2.   Fetching strategies When you choose to turn off the lazy initialization, you can also choose the way of how to get theassociated publisher object. The default strategy is to issue two SELECT statements for queryingthe book and publisher separately. This may be inefficient because you need to access database andexecute a query for two times.To ask Hibernate to retrieve the information in one shot, i.e. issue a single SELECT statement withtable join, we can change the “fetch” attribute of the association to “join” (default is “select”). <hibernate-mapping package= com.metaarchit.bookshop ><class name= Book table= BOOK >...<many-to-one name= publisher class= Publisher column= PUBLISHER_ID lazy= false fetch= join /></class></hibernate-mapping> If we inspect the SQL statements again, we will find that Hibernate is using a single SELECTstatement with table join to get the information. But is it also the case for using HQL queries? Session session = factory.openSession();try {Query query = session.createQuery( from Book where isbn = ? );query.setString(0, isbn);Book book = (Book) query.uniqueResult();return book;} finally {session.close();} Unfortunately, two SELECT statements are still executing for this case. It is because any HQLquery will be translated into SQL statement directly. To apply the joining fetch strategy, we need touse the following HQL syntax. Session session = factory.openSession();try {Query query = session.createQuery( from Book book left join fetch book.publisher where book.isbn = ? );query.setString(0, isbn);Book book = (Book) query.uniqueResult();return book;} finally {session.close();}
Related Search
We Need Your Support
Thank you for visiting our website and your interest in our free products and services. We are nonprofit website to share and download documents. To the running of this website, we need your help to support us.

Thanks to everyone for your continued support.

No, Thanks
Finding Carter (3) | Temporada 0 | Privacy Policy