Hibernate

What is Hibernate?
Hibernate is an object/relational mapping tool for Java environments. The term object/relational mapping (ORM) refers to the technique of mapping a data representation from an object model to a relational data model with a SQL-based schema.

Hibernate not only takes care of the mapping from Java classes to database tables (and from Java data types to SQL data types), but also provides data query and retrieval facilities and can significantly reduce development time otherwise spent with Manual data handling in SQL and JDBC.

Hibernates goal is to relieve the developer from 95 percent of common data persistence related programming tasks. Hibernate may not be the best solution for data-centric applications that only use stored-procedures to implement the business logic in the database, it is most useful with object-oriented domain models and Business logic in the Java-based middle-tier. However, Hibernate can certainly help you to remove or encapsulate vendor-specific SQL code and will help with the common task of result set translation from a tabular representation to a graph of objects.

Preparation of the Development Environment
1) Download hibernate from http://www.hibernate.org/

2) Extract the package and place all required libraries found in into into the  directory of your new development working directory. It should look like this:


 * lib
 * antlr.jar
 * cglib.jar
 * asm.jar
 * asm-attrs.jars
 * commons-collections.jar
 * commons-logging.jar
 * hibernate3.jar
 * jta.jar
 * dom4j.jar
 * log4j.jar

This is the minimum set of required libraries (note that we also copied hibernate3.jar, the main archive) for Hibernate at the time of writing.

3) If you want to work with Eclipse and Hibernate Tools you should install it using the Configuration Manager:
 * Update Site: http://download.jboss.org/jbosside/updates/development

Database model
If you will start to design a new database model, then you should consider the best practices to design the model in according to the hibernate rules:


 * Don’t use reserved keywords from java, hibernate or from the database to name tables, columns, view, stored procedures and other database objects. Avoid for example a column named date. You should use DateFrom, DateTo, DateStart, DateEnd, and so on.

Use of JavaBean classes
You can see that this class uses standard JavaBean naming conventions for property getter and setter methods, as well as private visibility for the fields. This is a recommended design - but not required. Hibernate can also access fields directly, the benefit of accessor methods is robustness for refactoring. The no-argument constructor is required to instantiate an object of this class through reflection. Example:

package events;

import java.util.*;

public class Event { private Long id;

private String title; private Date date;

public Event {}

public Long getId { return id; }

private void setId(Long id) { this.id = id; }

public Date getDate { return date; }

public void setDate(Date date) { this.date = date; }

public String getTitle { return title; }

public void setTitle(String title) { this.title = title; } }

The Mapping file
Hibernate needs to know how to load and store objects of the persistent class. This is where the Hibernate mapping file comes into play. The mapping file tells Hibernate what table in the database it has to access, and what columns in that table it should use.

 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.2.dtd">  [...] 

Between the two hibernate-mapping tags, include a class element. All persistent entity classes need such a mapping (again, there might be dependent classes later on, which are not first-class entities), to a table in the SQL database:

   


 * The id element is the declaration of the identifer property
 * The name="id" declares the name of the Java property -Hibernate will use the getter and setter methods to access the property.
 * The column attribute tells Hibernate which column of the EVENTS table we use for this primary key.
 * The nested generator element specifies the identifier generation strategy, in this case we used native, which picks the best strategy depending on the configured database (dialect).
 * The property element tells Hibernate which getter and setter methods to use.


 * Without the column attribute Hibernate by default uses the property name as the column name. This works fine for title. However, date is a reserved keyword in most database, so we better map it to a different name.


 * This mapping file should be saved as, right in the directory next to the Event Java class source file. The naming of mapping files can be arbitrary, however the suffix is a convention in the Hibernate developer community.

Hibernate Types
Source: Hibernate Types

The types we declare and use in the mapping files are not SQL database types and can be sometimes Java data types. These types are so called Hibernate Mapping Types, converters which can translate from Java to SQL data types and vice versa. You can custom value types.

The built-in basic mapping types of Hibernate are defined below:


 * integer, long, short, float, double, character, byte: Type mappings from Java primitives or wrapper classes to appropriate (vendor-specific) SQL column types.


 * boolean, yes_no, true_false: are all alternative encodings for a Java boolean or java.lang.Boolean.


 * string: A type mapping from java.lang.String to VARCHAR (or Oracle VARCHAR2).


 * date, time, timestamp: Type mappings from java.util.Date and its subclasses to SQL types DATE, TIME and TIMESTAMP (or equivalent).


 * calendar, calendar_date: Type mappings from java.util.Calendar to SQL types TIMESTAMP and DATE (or equivalent).


 * big_decimal, big_integer: Type mappings from java.math.BigDecimal and java.math.BigInteger to NUMERIC (or Oracle NUMBER).


 * locale, timezone, currency: Type mappings from java.util.Locale, java.util.TimeZone and java.util.Currency to VARCHAR (or Oracle VARCHAR2). Instances of Locale and Currency are mapped to their ISO codes. Instances of TimeZone are mapped to their ID.


 * class: A type mapping from java.lang.Class to VARCHAR (or Oracle VARCHAR2). A Class is mapped to its fully qualified name.


 * binary: Maps byte arrays to an appropriate SQL binary type.


 * text: Maps long Java strings to a SQL CLOB or TEXT type.


 * serializable: Maps serializable Java types to an appropriate SQL binary type. You may also indicate the Hibernate type serializable with the name of a serializable Java class or interface that does not default to a basic type.


 * clob, blob: Type mappings for the JDBC classes java.sql.Clob and java.sql.Blob. These types may be inconvenient for some applications, since the blob or clob object may not be reused outside of a transaction. (Furthermore, driver support is patchy and inconsistent.)


 * imm_date, imm_time, imm_timestamp, imm_calendar, imm_calendar_date, imm_serializable, imm_binary: Type mappings for what are usually considered mutable Java types, where Hibernate makes certain optimizations appropriate only for immutable Java types, and the application treats the object as immutable. For example, you should not call for an instance mapped as imm_timestamp. To change the value of the property, and have that change made persistent, the application must assign a new (nonidentical) object to the property.

Hibernate configuration
Extracted from

In this tutorial we use the HSQL DB, a java-based SQL DBMS, that can be downloaded from the HSQL DB website. Actually, you only need the hsqldb.jar from this download. Place this file in the lib/ directory of the development folder.

 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">





org.hsqldb.jdbcDriver jdbc:hsqldb:hsql://localhost sa 

1

org.hibernate.dialect.HSQLDialect

thread

<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider

<property name="show_sql">true

<property name="hbm2ddl.auto">create

<mapping resource="events/Event.hbm.xml"/> <mapping resource="events/Person.hbm.xml"/>

</session-factory>

</hibernate-configuration>

Explanations:


 * The first four property elements contain the necessary configuration for the JDBC connection.
 * The dialect property element specifies the particular SQL variant Hibernate generates.
 * The hbm2ddl.auto option turns on automatic generation of database schemas - directly into the database.
 * Finally, we add the mapping file(s) for persistent classes to the configuration.
 * Copy this file into the source directory, so it will end up in the root of the classpath. Hibernate automatically looks for a file called hibernate.cfg.xml in the root of the classpath, on startup.

Observations:


 * If you have several databases, use several <session-factory> configurations, usually in several configuration files (for easier startup).

SQL Dialects
You should always set the hibernate.dialect property to the correct org.hibernate.dialect.Dialect subclass for your database. If you specify a dialect, Hibernate will use sensible defaults for some of the other properties listed above, saving you the effort of specifying them manually.

Building a SessionFactory
A SessionFactory can open up new Session's. A Session represents a single-threaded unit of work, the SessionFactory is a thread-safe global object, instantiated once.

package util;

import org.hibernate.*; import org.hibernate.cfg.*;

public class HibernateUtil {

private static final SessionFactory sessionFactory;

static { try { // Create the SessionFactory from hibernate.cfg.xml sessionFactory = new Configuration.configure.buildSessionFactory; } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); }   }

public static SessionFactory getSessionFactory { return sessionFactory; } }

Session
You can find more information here.

The main runtime interface between a Java application and Hibernate. This is the central API class abstracting the notion of a persistence service.

The lifecycle of a Session is bounded by the beginning and end of a logical transaction. (Long transactions might span several database transactions.)

The main function of the Session is to offer create, read and delete operations for instances of mapped entity classes. Instances may exist in one of three states:


 * transient: never persistent, not associated with any Session
 * persistent: associated with a unique Session
 * detached: previously persistent, not associated with any Session

Transient instances may be made persistent by calling, or. Persistent instances may be made transient by calling. Any instance returned by a or  method is persistent. Detached instances may be made persistent by calling, , or. The state of a transient or detached instance may also be made persistent as a new persistent instance by calling.

and result in an SQL INSERT,  in an SQL DELETE and  or  in an SQL UPDATE. Changes to persistent instances are detected at flush time and also result in an SQL UPDATE. and result in either an INSERT or an UPDATE.

It is not intended that implementors be threadsafe. Instead each thread/transaction should obtain its own instance from a SessionFactory.

A Session instance is serializable if its persistent classes are serializable.

Session main methods

 * Begin a unit of work and return the associated Transaction object. If a new underlying transaction is required, begin the transaction. Otherwise continue the new work in the context of the existing underlying transaction. The class of the returned Transaction object is determined by the property hibernate.transaction_factory.
 * Begin a unit of work and return the associated Transaction object. If a new underlying transaction is required, begin the transaction. Otherwise continue the new work in the context of the existing underlying transaction. The class of the returned Transaction object is determined by the property hibernate.transaction_factory.


 * Get the JDBC connection of this Session.
 * Get the JDBC connection of this Session.


 * Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance. (If the instance, or a proxy for the instance, is already associated with the session, return that instance or proxy.)
 * Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance. (If the instance, or a proxy for the instance, is already associated with the session, return that instance or proxy.)


 * Return the identifier of an entity instance cached by the Session, or throw an exception if the instance is transient or associated with a different Session.
 * Return the identifier of an entity instance cached by the Session, or throw an exception if the instance is transient or associated with a different Session.


 * Remove this instance from the session cache. Changes to the instance will not be synchronized with the database. This operation cascades to associated instances if the association is mapped with cascade="evict".
 * Remove this instance from the session cache. Changes to the instance will not be synchronized with the database. This operation cascades to associated instances if the association is mapped with cascade="evict".


 * Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists. Use this only to retrieve an instance that you assume exists, where non-existence would be an actual error.
 * Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists. Use this only to retrieve an instance that you assume exists, where non-existence would be an actual error.


 * Persist the state of the given detached instance, reusing the current identifier value. This operation cascades to associated instances if the association is mapped with cascade="replicate".
 * Persist the state of the given detached instance, reusing the current identifier value. This operation cascades to associated instances if the association is mapped with cascade="replicate".


 * Persist the given transient instance, first assigning a generated identifier. (Or using the current value of the identifier property if the assigned generator is used.) This operation cascades to associated instances if the association is mapped with cascade="save-update".
 * Persist the given transient instance, first assigning a generated identifier. (Or using the current value of the identifier property if the assigned generator is used.) This operation cascades to associated instances if the association is mapped with cascade="save-update".


 * Either save or update the given instance, depending upon the value of its identifier property. By default the instance is always saved. This behaviour may be adjusted by specifying an unsaved-value attribute of the identifier property mapping. This operation cascades to associated instances if the association is mapped with cascade="save-update".
 * Either save or update the given instance, depending upon the value of its identifier property. By default the instance is always saved. This behaviour may be adjusted by specifying an unsaved-value attribute of the identifier property mapping. This operation cascades to associated instances if the association is mapped with cascade="save-update".


 * Update the persistent instance with the identifier of the given detached instance. If there is a persistent instance with the same identifier, an exception is thrown. This operation cascades to associated instances if the association is mapped with cascade="save-update".
 * Update the persistent instance with the identifier of the given detached instance. If there is a persistent instance with the same identifier, an exception is thrown. This operation cascades to associated instances if the association is mapped with cascade="save-update".


 * Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with cascade="merge".
 * Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with cascade="merge".


 * Make a transient instance persistent. This operation cascades to associated instances if the association is mapped with cascade="persist".
 * Make a transient instance persistent. This operation cascades to associated instances if the association is mapped with cascade="persist".


 * Remove a persistent instance from the datastore. The argument may be an instance associated with the receiving Session or a transient instance with an identifier associated with existing persistent state. This operation cascades to associated instances if the association is mapped with cascade="delete".
 * Remove a persistent instance from the datastore. The argument may be an instance associated with the receiving Session or a transient instance with an identifier associated with existing persistent state. This operation cascades to associated instances if the association is mapped with cascade="delete".


 * Obtain the specified lock level upon the given object. This may be used to perform a version check (LockMode.READ), to upgrade to a pessimistic lock (LockMode.UPGRADE), or to simply reassociate a transient instance with a session (LockMode.NONE). This operation cascades to associated instances if the association is mapped with cascade="lock".
 * Obtain the specified lock level upon the given object. This may be used to perform a version check (LockMode.READ), to upgrade to a pessimistic lock (LockMode.UPGRADE), or to simply reassociate a transient instance with a session (LockMode.NONE). This operation cascades to associated instances if the association is mapped with cascade="lock".


 * Re-read the state of the given instance from the underlying database. It is inadvisable to use this to implement long-running sessions that span many business tasks. This method is, however, useful in certain special circumstances. For example:
 * Re-read the state of the given instance from the underlying database. It is inadvisable to use this to implement long-running sessions that span many business tasks. This method is, however, useful in certain special circumstances. For example:


 * where a database trigger alters the object state upon insert or update
 * after executing direct SQL (eg. a mass update) in the same session
 * after inserting a Blob or Clob

Making an object persistent
The first thing you want to do with a Session is make a new transient object persistent. To do so, you use the method:

User user = new User; user.getName.setFirstname("John"); user.getName.setLastname("Doe");

Session session = sessions.openSession; Transaction tx = session.beginTransaction; session.save(user); tx.commit; session.close;

First, we instantiate a new transient object user as usual. Of course, we might also instantiate it after opening a Session; they aren’t related yet. We open a new Session using the SessionFactory referred to by sessions, and then we start a new database transaction.

A call to makes the transient instance of User persistent. It’s now associated with the current Session. However, no SQL INSERT has yet been executed. The Hibernate Session never executes any SQL statement until absolutely necessary. The changes made to persistent objects have to be synchronized with the database at some point. This happens when we the Hibernate Transaction.

In this case, Hibernate obtains a JDBC connection and issues a single SQL INSERT statement. Finally, the Session is closed and the JDBC connection is released. Note that it’s better (but not required) to fully initialize the User instance before associating it with the Session. The SQL INSERT statement contains the values that were held by the object at the point when was called. You can, of course, modify the object after calling, and your changes will be propagated to the database as an SQL UPDATE.

If one of the UPDATE or INSERT statements made on tx.commit fails, all changes made to persistent objects in this transaction will be rolled back at the database level. However, Hibernate does not roll back in-memory changes to persistent objects; this is reasonable since a failure of a database transaction is normally nonrecoverable and you have to discard the failed Session immediately.

Loading and Storing objects
Hibernate now takes care of the SQL and executes INSERTs on the database, if you use the word “store” as argument for the application or execute the SELECT statement if you use the word “list” as argument. See the example:

package events; import org.hibernate.Session; import java.util.Date; import util.HibernateUtil;

public class EventManager {

public static void main(String[] args) { EventManager mgr = new EventManager;

if (args[0].equals("store")) { mgr.createAndStoreEvent("My Event", new Date); }  else if (args[0].equals("list")) { List events = mgr.listEvents; for (int i = 0; i < events.size; i++) { Event theEvent = (Event) events.get(i); System.out.println("Event: " + theEvent.getTitle +                                  " Time: " + theEvent.getDate); }

HibernateUtil.getSessionFactory.close; }

private Long createAndStoreEvent(String title, Date theDate) {

Session session = HibernateUtil.getSessionFactory.getCurrentSession; session.beginTransaction;

Event theEvent = new Event; theEvent.setTitle(title); theEvent.setDate(theDate);

session.save(theEvent);

session.getTransaction.commit;

return theEvent.getId; }

private List listEvents {

Session session = HibernateUtil.getSessionFactory.getCurrentSession; session.beginTransaction;

List result = session.createQuery("from Event").list;

session.getTransaction.commit;

return result; } }

What we do here is use an HQL (Hibernate Query Language) query to load all existing Event objects from the database. Hibernate will generate the appropriate SQL, send it to the database and populate Event objects with the data. You can create more complex queries with HQL, of course.

Links
Relationships

Uni-Directional Associations
See the following example for a mapping between the table Events and Person. A person can participate in none or many events and one event can have none or many particpants. The Database schema for this mapping is:

_____________       __________________   |             |      |                  |       _____________   |   EVENTS    |      |   PERSON_EVENT   |      |             | |_____________|     |__________________|      |    PERSON   | |            |      |                  |      |_____________|   | *EVENT_ID   | <--> | *EVENT_ID        |      |             | | EVENT_DATE |      | *PERSON_ID       | <--> | *PERSON_ID  | | TITLE      |      |__________________|      |  AGE        | |_____________|                               |  FIRSTNAME  | | LASTNAME   | |_____________|

The class Person is: public class Person {

private Set events = new HashSet;

public Set getEvents { return events; }

public void setEvents(Set events) { this.events = events; } }

The file is:

<class name="events.Person" table="PERSON">  </id>

<set name="events" table="PERSON_EVENT"> <key column="PERSON_ID"/> <many-to-many column="EVENT_ID" class="events.Event"/>

Hibernate supports all kinds of collection mappings, a   being most common. For a many-to-many association (or n:m entity relationship), an association table is needed. Each row in this table represents a link between a person and an event. The table name is configured with the table attribute of the set element. The identifier column name in the association, for the person's side, is defined with the   element, the column name for the event's side with the column attribute of the <many-to-many>. You also have to tell Hibernate the class of the objects in your collection (correct: the class on the other side of the collection of references). This example shows a uni-directional association. In this case there is no synchronization between the classes Person and Events.

Bi-Directional Associations
Next we are going to map a bi-directional association - making the association between person and event work from both sides in Java. Of course, the database schema doesn't change.

First, add a collection of participants to the Event class:

private Set participants = new HashSet;

public Set getParticipants { return participants; }

public void setParticipants(Set participants) { this.participants = participants; }

Now map this side of the association too, in.

<set name="participants" table="PERSON_EVENT" inverse="true"> <key column="EVENT_ID"/> <many-to-many column="PERSON_ID" class="events.Person"/>

As you see, these are normal set mappings in both mapping documents. Notice that the column names in key and many-to-many are swapped in both mapping documents. The most important addition here is the inverse="true" attribute in the set element of the Event's collection mapping.

What this means is that Hibernate should take the other side - the Person class - when it needs to find out information about the link between the two. This will be a lot easier to understand once you see how the bi-directional link between our two entities is created.

Observations:


 * First, keep in mind that Hibernate does not affect normal Java semantics.


 * if we want to make this link working bi-directional, we have to do the same on the other side - adding a Person reference to the collection in an Event. This "setting the link on both sides" is absolutely necessary and you should never forget doing it.

Many developers program defensive and create a link management methods to correctly set both sides, e.g. in Person:

protected Set getEvents { return events; }

protected void setEvents(Set events) { this.events = events; }

public void addToEvent(Event event) { this.getEvents.add(event); event.getParticipants.add(this); }

public void removeFromEvent(Event event) { this.getEvents.remove(event); event.getParticipants.remove(this); }

Notice that the get and set methods for the collection are now protected - this allows classes in the same package and subclasses to still access the methods, but prevents everybody else from messing with the collections directly (well, almost). You should probably do the same with the collection on the other side.

HQL Expressions
Expressions allowed in the where clause include most of the kind of things you could write in SQL:


 * mathematical operators +, -, *, /
 * binary comparison operators =, >=, <=, <>, !=, like
 * logical operations and, or, not
 * Parentheses, indicating grouping
 * in, not in, between, is null, is not null, is empty, is not empty, member of and not member of
 * "Simple" case, case ... when ... then ... else ... end, and "searched" case, case when ... then... else ... end
 * string concatenation ...||... or concat(...,...)
 * current_date, current_time, current_timestamp
 * second(...), minute(...), hour(...), day(...), month(...), year(...),
 * Any function or operator defined by EJB-QL 3.0: substring, trim, lower, upper, length, locate, abs, sqrt, bit_length, mod
 * coalesce and nullif
 * str for converting numeric or temporal values to a readable string
 * cast(... as ...), where the second argument is the name of a Hibernate type, and extract(... from...) if ANSI cast and extract is supported by the underlying database
 * the HQL index function, that applies to aliases of a joined indexed collection
 * HQL functions that take collection-valued path expressions: size, minelement, maxelement, minindex, maxindex, along with the special elements and indices functions which may be quantified using some, all, exists, any, in.
 * Any database-supported SQL scalar function like sign, trunc, rtrim, sin
 * JDBC-style positional parameters ?
 * named parameters :name, :start_date, :x1
 * SQL literals 'foo', 69, 6.66E+2, '1970-01-01 10:00:01.0'
 * Java public static final constants eg.Color.TABBY

Named Queries
You can use named queries to optimize the use of the statement cache. Meaning Hibernate will pre-parse the HQL, create the statement and have it ready to go for named queries. For an "ad hoc" query this happens every time on the fly. This can make a difference in performance, but the main advantage is that any HQL errors are discovered at startup rather than on the fly.

You have to put the named queries after the   tag in the file. Example :

 <class name="br.jaraujo.project.pojo.TradeList" table="TradeList"> ... <query name="tradelist.update.startDate"> UPDATE TradeList tl SET tl.startUpdatedDate=:startDate1 WHERE tl.startUpdatedDate > :startDate2 AND tl.codTradeList=:id </hibernate-mapping> Example of use: Hibutil.beginTransaction; Query query = Hibutil.getSession.getNamedQuery("tradelist.update.startDate"); query.setParameter("startDate1", config.getStartDate); query.setParameter("startDate2", config.getStartDate); query.setParameter("id", config.getSelectedTradeList.getCodTradeList); query.executeUpdate; Hibutil.commitTransaction;

Lazy Initialization and Fetching Strategies
Lazy Initialization is a very important concept designed by the Hibernate team. It improves the performance of your application in some cases. It keeps the memory free of useless associated objects or useless attributes. At the end, it may improve the network traffic and avoid that the database engine works hard for nothing. But it can also be a knightmare if it is misused or not well understood.

Lazy Initialization means that an associated object is fetched ONLY when the application invokes an operation upon that collection. This is the default fetching mode defined in the XML file for POJO mapping. The property lazy="proxy" is the default/implicit value for all mapped objects (classes, columns, collections, etc.).

The associated object refers normally to a Collection or Single Object. These objects shall be mapped in the O/R Hibernate mapping metadata (XML files). Lazy Initialization uses a Proxy object to hit the database and to invoke methods on the associated object when needed.

The chapter 19 of the "Hibernate Reference Documentation" is dedicated to the improvement of performance and describes the different Fetching strategies. This section is a summary of this important chapter and analyzes some problems, solutions and strategies in order to overcome problems around the Lazy Initialization.

You should keep in mind :


 * The Fetching strategy is coded in the O/R mapping metadata.
 * A fetching strategy is the strategy Hibernate will use for retrieving associated objects.
 * The word fetch is used to tune performance. It is related to how the associated objects are fetched (what SQL is used).
 * The word lazy is used by Hibernate team to define a contract for what data is always available in any detached instance of a particular class.
 * A default fetching strategy can be overridden by a particular HQL or Criteria query.

A typical Lazy Initialization problem is presented below:

s = sessions.openSession; Transaction tx = s.beginTransaction; User u = (User) s.createQuery("from User u where u.name=:userName") .setString("userName", userName).uniqueResult; Map permissions = u.getPermissions; tx.commit; s.close; Integer accessLevel = (Integer) permissions.get("accounts"); // Error! LazyInitializationException

The collection permissions was not initialized and is called by the Hibernate team as a Detached Object. By default, Hibernate does not support lazy initialization for detached objects. Therefore it is important to define a fetching strategy and understand how lazy initialization works.

If your application is getting the exception org.hibernate.LazyInitializationException you can use one of the proposed solutions below.

Solution 1: Fetch the associated objects
To solve this problem you have to use explicitly the command fetch in the hql statement in order the permissions are loaded together with the users. Example:

s = sessions.openSession; Transaction tx = s.beginTransaction; User u = (User) s.createQuery("from User u left join fetch u.permissions p where u.name=:userName") .setParameter("userName", userName).uniqueResult; Map permissions = u.getPermissions; tx.commit; s.close;

u.permissions is a property mapped in the class (POJO) User.

Solution 2: Load only the associated object
If you got already the main object, load the associated object.

It is very common in a client/server application that you read something from the database in one GUI and read associated objects to that object in other GUI. In this case, the Hibernate team advices to NEVER keep a looooong session during the "user think-time".

Well, the solution for the problem presented in the previous section is shown below:

s = sessions.openSession; Transaction tx = s.beginTransaction; Map permissions = (Map) s.createQuery("Select u.getPermissions from User u where u.userid=:userid") .setParameter("userid", u.getID).uniqueResult; tx.commit; s.close; Integer accessLevel = (Integer) permissions.get("accounts");

Solution 3: Disable proxying
Use a non-lazy collection or association, by specifying lazy="false" for the association mapping. It explicitly disables proxying. For example, you should add the code below to the O/R mapping metadata called :

<map name="permissions" inverse="true" fetch="select" lazy="false"> <map-key column="name" type="string"/> <one-to-many class="org.myproject.Permissions"/> You should keep in mind :

lazy="true"
 * you load the data only if you need it
 * you can access the data only while in persistent mode, i.e. after new Transaction and before Transaction.commit

lazy="false"
 * it specifies that the association will always be eagerly fetched
 * you are loading the whole state of the object when you load it, including all associated objects
 * it can decrease database and application performance
 * do not overuse this property, otherwise Hibernate needs to fetch the entire database into memory in every transaction!

Solution 4: Open Session In View
This particular solution applies only if you are coding an web application. The original solution for this issue is well described at Open Session in View.

A common issue in a typical web application is the rendering of the view, after the main logic of the action has been completed, and therefore, the Hibernate Session has already been closed and the database transaction has ended. If you access detached objects that have been loaded in the Session inside your JSP (or any other view rendering mechanism), you might hit an unloaded collection or a proxy that isn't initialized. The exception you get is: LazyInitializationException: Session has been closed (or a very similar message). Of course, this is to be expected, after all you already ended your unit of work.

You shall add an interceptor into your and enable a filter to run for all HTTP requests. Example: <filter-name>HibernateFilter</filter-name> <filter-class>my.package.HibernateThreadFilter</filter-class> <filter-mapping> <filter-name>HibernateFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>


 * The tag   is used to explicitly initialize all associations and collections required before returning it.
 * The tag  <filter-mapping>  is used to to keep the session open until the view is done rendering (commonly referred to as 'Open Session In View').

Problems with schema and catalog names
If you are having troubles trying to update a database schema and getting some errors like these: DEBUG: org.hibernate.tool.hbm2ddl.SchemaUpdate - create table proxtel.company (codCompany integer not null ERROR: org.hibernate.tool.hbm2ddl.SchemaUpdate - Unsuccessful: create table proxtel.company (codCompany integer not null, ERROR: org.hibernate.tool.hbm2ddl.SchemaUpdate - invalid schema name: proxtel in statement [create table proxtel.company]

Then you have to check the following solutions:


 * Try to remove the property catalog of the element class.

<class name="de.jaraujo.proxtel.pojo.Company" table="company" catalog="proxtel">
 * Try to add or change the properties hibernate.default_schema and hibernate.default_catalog of the file

<property name="hibernate.default_schema">myschema

<property name="hibernate.default_catalog">mycatalog

MySQL Configuration
Here is an example of the file in order to use MySQL database.

<hibernate-configuration> <session-factory name="HibernateSessionFactory"> org.hibernate.dialect.MySQLInnoDBDialect <property name="connection.driver_class">com.mysql.jdbc.Driver <property name="connection.url">jdbc:mysql://localhost:3306/mydb <property name="connection.username">my_user <property name="connection.password">my_password </session-factory> </hibernate-configuration>

How to register special database commands to Hibernate Dialect
To register a specific function of your database to an existing Hibernate Dialect you have to register this function as the example below:

Firstly, create a class, extends the original Hibernate Dialect and register the desired function. Example:

package mydemo.dialect.test; import org.hibernate.Hibernate; import org.hibernate.dialect.MySQL5InnoDBDialect; import org.hibernate.dialect.function.StandardSQLFunction; public class MySQL5InnoDBStddevDialect extends MySQL5InnoDBDialect { public MySQL5InnoDBStddevDialect { super; registerFunction("stddev", new StandardSQLFunction("stddev", Hibernate.DOUBLE) ); }  }

Secondly, use this class as the offcial Hibernate Dialect of your application. Just register it in your. Example:

... <property name="hibernate.dialect">mydemo.dialect.test.MySQL5InnoDBStddevDialect ...

How to read a POJO using different constructors
Sometimes you want to read only some attributes/fields of a database table mapped to a object in your application, i.e. mapped to a POJO, but you do not want to receive the result in the format Object[] since you need to work later with the POJO that has only less attributes. I call this object as incomplete POJO.

This approach increases the performance of your application, uses a minimal memory storage allocation, while decrease network and database traffic.

First, you have to create a new constructor for your POJO. Example:

public class Exchange { private Integer codExchange; private String name; private String abbreviation; private String website; private Date openTime; private Date closeTime; // Constructor 1 public Exchange { }   // Constructor 2 public Exchange(Integer codExchange, String name) { this.codExchange = codExchange; this.name = name; }   ...     Getters and Setters are coded here ... } Now you can execute the new constructor inside the HSQL statement to get a list of exchanges that have only the fields codExchange and name:

String hsql = "SELECT new Exchange(exch.codExchange, exch.name) FROM Exchange exch"; Hibutil.beginTransaction; Session session = getSession; List<Exchange> exchanges = session.createQuery(hsql).list; Hibutil.commitTransaction;

Getting the table name of a POJO
// initialize session factory SessionFactory sessionFactory = configuration.configure.buildSessionFactory; // instatiate your POJO POJO1 pojo = new POJO1; // get the metadata of the POJO ClassMetadata mMetaData = sessionFactory.getClassMetadata(pojo.getClass); // now, you can get the table name String tableName = mMetaData.getEntityName;

Date versus Timestamp
When you create an application that uses Hibernate and you need to map a Date/Time field of a table, but you do not need to work with nanoseconds, you should define your own Date/Time UserType conversor for Hibernate.

The problem about using the default Hibernate type (type="timestamp") is that you always get a java.sql.Timestamp in your java.util.Date field. In this case any calls to the methods equals or compareTo will be wrong, although both dates have the same date and time.

Take a look on the following sample code: java.util.Date date = new java.util.Date; java.sql.Timestamp tstamp = new java.sql.Timestamp( date.getTime ); System.out.println("tstamp.equals(date): " + tstamp.equals(date)); System.out.println("date.equals(tstamp): " + date.equals(tstamp));

The output is: tstamp.equals(date): false date.equals(tstamp): true

The result should be true in both cases. It is a known issue regarding this incompatibility between java.util.Date and java.sql.Timestamp in the Java World and it is not a bug of Hibernate.

The safest approach is to define your own Date/Time UserType conversor for Hibernate. Example:

<property name="dateField" type="yourpackage.TimestampToDate"> <column index="idx_timestamp_rt" length="19" name="dateField" not-null="true">

You have to change all type="timestamp" to type="yourpackage.TimestampToDate" in your .hbm.xml files. The source code for yourpackage.TimestampToDate could be:

public class TimestampToDate extends TimestampType { @Override public Object get(ResultSet rs, String name) throws SQLException { Timestamp timestamp = (Timestamp) super.get(rs, name); if (timestamp == null) { return null; }       return new Date(timestamp.getTime); } } // TimestampToDate

Other solution is to change all java.util.Date in your application to java.sql.Timestamp.

Record Count of an Entity
/** * Gets the record count of a table mapped to a POJO. * * @param entityName POJO name. * @return Record count. * @throws HibernateException Hibernate Exception */ public static long getRecordCount(String entityName) throws HibernateException { Session session = getSession; Query query = session.createQuery("select count(*) from " + entityName); Long recordcount = Long.parseLong(query.uniqueResult.toString); return recordcount; }