Sunday, November 10, 2013

Hibernate Tutorial - Part II

For part I refer:
Hibernate tutorial Part - I

In this post we will see how the entity mapping is done. Lets take an example of a library management application for simplicity and take a look at the various possible mappings.

Lets say we need to create an entity 'Book'. We will create a Book POJO. This will be mapped to a table named 'Book'. The book table will have the following columns.

  1. BOOK_ID (Primary Key, Type: Number) driven by sequence book_id_seq
  2. BOOK_NAME (Type: Varchar2(50)
  3. PUBLISH_DATE (Type: Date)
  4. BOOK_PREVIEW (Type: clob)
The Book class with entity annotations will be as below:

@Entity 
@Table(name="book")
@org.hibernate.annotations.Entity(
        dynamicUpdate = true
)
public class Book implements Serializable{

    private static final String BOOK_SEQUENCE = "book_id_seq";

    @Id
    @Column(name="BOOK_ID")
    @SequenceGenerator(
         name=BOOK_SEQUENCE,
         sequenceName=BOOK_SEQUENCE)
         @GeneratedValue(strategy=GenerationType.SEQUENCE, generator=BOOK_SEQUENCE)
    private long number;
    
    @Column(name="BOOK_NAME")
    private String name;
    
    @Temporal(DATE)
    @Column(name="PUBLISH_DATE")
    private Date publishDate; 
    
    @Transient
    private boolean isPopular;
    
    @Column(name="BOOK_PREVIEW")
    @Lob
    @Basic(fetch=FetchType.LAZY)
    private String preview;
    
    public Book(){
    }
    
    //setters and getters

}

The annotations used above are described in detail:
  1. @table is used to map the class to a particular table. There are other options here like the inheritance strategy, which will be explained later.
  2. @column is used to map a field to a particular column. This annotation could be applied at field level or at method level (getter). It is advised to follow a common practice throughout.
  3. @Id is used to indicate primary key columns with an appropriate ID generator strategy as explained in the previous post. In the above example, we are using sequence generator strategy. The sequence name is mapped through 'sequenceName' option.
  4. @temporal is used to map date or timestamp fields. Possible values being TIME/DATE/TIMESTAMP.
  5. @Transient is used for fields which are not persistent and which will not be saved/retrieved to/from the database. In the above example, isPopular could be a derived field and  hence marked as transient.
  6. @lob is used to map CLOB or BLOB columns. In the above example, preview provides a brief description of the book and hence is a CLOB column. For blob types, you might want to use byte[] data type in java to represent the blob data.
  7. FetchType.Lazy is used to indicate lazy loading. By default, hibernate performs eager loading, which means all the properties are loaded when the entity is loaded. This strategy would cause performance issues when the property is a clob/blob field. In the above example, 'preview' is loaded lazily. i.e, loaded when the first call to the getPreview() is performed. 

Dynamic Inserts/Updates:

In the above example, we have annotated the Book class with Entity annotation from the hibernate package. The first one is from 'javax.persistence.Entity' package. The hibernate Entity annotation has two options 'dynamicInsert' and 'dynamicUpdate'.

What this means is that, while inserting or updating the Book table, Hibernate will insert only those columns whose values are non null. SImilarly, if dynamicUpdate is true, Hibernate will update only those columns whose values are not modified. Hibernate will keep track of which columns are modified in the current session. 
These two options will cause an increase in performance, if your tables have large number of columns and you have scenarios wherein, not all columns are inserted/updated every time. 

However, use this option with caution. If you blindly apply this strategy in every single case, then it might actually backfire. Since Hibernate has to keep dynamically prepare the statements and also has to apply additional conditions for null checking or checking for modified fields, this might actually bring down performance.  So exercise this option with care.

                                       Continued.....

Monday, November 4, 2013

Hibernate Tutorial - Part I

Overview:

Hibernate is an Object relational mapping (ORM) tool which will help us map Java objects to the underlying database objects. It will help us perform various operations on objects and hibernate will translate it to the DBMS operations and saves us from writing sql queries.

An equally important aspect is the importance of object orientated principles which need not be compromised when we use Hibernate. If we go with plain old sql style of design, then due to the disconnect between the object oriented design and the DBMS design, often the object oriented design is compromised.

For instance, concepts like inheritance, composition do not have a corresponding representation in the DBMS world. Similarly, we cannot truly represent a bi-drectional navigation and mapping between two entities (say for eg, Author and Book) in the DBMS world. These short comings could be overcome if we use Hibernate and we can minimize the influence of DBMS design on the object oriented design.

When we use Hibernate, we can map the entity classes (i.e POJO classes) to the corresponding database tables and the fields of the classes relate to the columns (explained in detail as we move along).

Hibernate Session:

Session is a single threaded object which keeps track of all the persistent objects within it. It offers CRUD operations for the mapped entity classes.  A transaction starts and ends within a session.

So a typical psuedo code while using session will look like:

  1. Open session
  2. Start transaction
  3. Save/Load objects into the session
  4. Commit transaction
  5. Close session
A session is obtained from a Session factory which is a thread safe object. The factory could be initialized through a Configuration object, by providing the connection details of the database. The configuration could be provided as a xml or as a properties file.
Hibernate supports use of third party connection pools which could be plugged in seamlessly.
C3p0 is a popular connection pool provider which could be used.

Entity Mappings:

The entity to schema mapping could be either provided as a xml file or as annotations within the entity class. We will be using annotations in the examples in the following posts.

The entity objects or the POJOs should follow the following rules:
  1. Needs no-arg constructor
  2. Could be abstract or extend non persistent class
  3. Class cannot be final and no final methods (for Proxy generation)

ID Generators:

For generating primary keys, Hibernate supports various types of ID generators to chose from.
  1. Native  - The native identity generator picks other identity generators like identity,sequence, or hilo, depending on the capabilities of the underlying database. Use this generator to keep your mapping metadata portable to different database management systems.
  2. Identity -This generator supports identity columns in DB2, MySQL, MS SQL Server, Sybase.
  3. Sequence - This generator supports sequences.
  4. Increment - This generator reads the maximum (numeric) primary key column value of the table and increments the value by one each time a new row is inserted.
  5. Hilo - A high/low algorithm is an efficient way to generate identifiers of type long, given a table and column (by default hibernate_unique_key and next, respectively) as a source of high values. The high/low algorithm generates identifiers that are unique only for a particular database. High  values are retrieved from a global source and are made unique by adding a local low value.
  6. Seqhilo - works like the regular hilo generator, except it uses a named database sequence to generate high values.
  7. Uuid.hex - generates a unique value based on appending the following values:IP Address,the startup time of current JVM,the current time,and counter value.It support all database and has no paameter.
  8. Guid - This generator provides a database-generated globally unique identifier string on MySQL and SQL Server.
  9. Select -This generator retrieves a primary key assigned by a database trigger by selecting the row by some unique key and retrieving the primary key value. An additional unique candidate key column is required for this strategy,and the key option has to be set to the name of the unique key column.
In the following posts, we will take a look at the various features of Hibernate along with code examples.

                                                                                                       Continued...