Object Persistence Using Hibernate: An Object-Relational Mapping Framework For Object Persistence
Object Persistence Using Hibernate: An Object-Relational Mapping Framework For Object Persistence
Object - Relational mapping Transparent persistence & retrieval of objects Persistence of associations and collections Guaranteed uniqueness of an object (within a session)
Hibernate Features
O-R mapping using ordinary JavaBeans Can set attributes using private fields or private setter methods Lazy instantiation of collections (configurable) Polymorphic queries, object-oriented query language Cascading persist & retrieve for associations, including collections and many-to-many Transaction management with rollback Can integrate with other container-provided services
Application Architecture
User Interface UI event Application Logic data request data xfer object
domain object
Domain Objects
SessionFactory hibernate.cfg.xml *.hbm.xml class mappings Foundation Classes
DAO
Hibernate API
Hibernate
domain object
JDBC API
JDBC
ResultSet, etc.
Another View
Exercise 1
create an EventManager project add Hibernate libraries to the project add JAR for database driver
O-R mapping file for a class copied here by IDE during build copied here by IDE during build
http://www.hibernate.org
Libraries are in lib/ directory of Hibernate distribution. Which ones do you need?
In your IDE:
create a Hibernate "library" add JARs to the library better than copying JAR files to your project
Required Libraries hibernate3.jar antlr-2.7.6.jar asm.jar cglib.jar commons-collections.jar commons-logging.jar dom4j.jar ehcache.jar jta.jar log4j.jar // and maybe xml-apis.jar
XML Syntax, 1
Tree structure & Scope: all elements must have a closing tag
<class name="Event" table="EVENTS"> a start element <property name="location" /> element start & end </class> an end tag
XML Syntax, 2
Special characters: < > & ' " must use reference except in CDATA
<message> "Hello <b>world</b>" </message>
Logging
if you use Log4j, create a log4j.properties in your application source root directory.
Copy this file from the Hibernate etc/ directory.
Sample log4j.properties
Configuration logging of Hibernate: log4j.logger.org.hibernate=warn Log the SQL generated by Hibernate: #log4j.logger.org.hibernate.SQL=debug Log JDBC bind parameters (can be security leak): log4j.logger.org.hibernate.type=info
Exercise 2
Define a Location class and LOCATIONS table Write the class Create a mapping file for Location: Location.hbm.xml
// a no argument constructor
int getId( ) { return id; } void setId( int id ) { this.id = id; } String getName( ) { return name; } void setName( String n ) { this.name = n; } String getAddress( ) { return address; } void setAddress( String a ) { address = a; }
public int getId( ) { return id; } private void setId( int id ) { this.id = id; } public String getName( ) { return name; } private void setName( String n ) { this.name = n; } public String getAddress( ) { return address; } private void setAddress( String a ) { address = a; } }
to tell Hibernate to set the field values directly (don't use the "set" method) in the class mapping file write:
<hibernate-mapping default-access="field"> ...
PK
Constraints
You omit elements if Hibernate can guess the value itself: <property <!-- omit <property <!-- omit <property name="address" column="ADDRESS" type="string"/> data type and Hibernate will determine it --> name="address" column="ADDRESS"/> column if same as attribute (ignoring case)--> name="address"/>
Project configured for Hibernate Hibernate configuration file Location class and mapping file Location.hbm.xml Configure a database schema
Exercise 3
In one session get the same location two times and compare using (ku1 == ku2). Are they same? In different sessions get the same location and compare (ku1 == ku2). Are they same?
Modify a location inside a session. Does database change? Reattach a modified object to new session. Does database change?
cascade="none"
"all" "save-update"
Error: LazyInstantiationException
Two Solutions
1. Modify our code: getLocation( ) before closing the session.
List<Event> list = (List<Event>)query.list( ); for(Event e : list ) out.printf("%d %s %s\n", e.getId(), e.getName(), e.getLocation().getName() ); tx.commit( );
2. Tell Hibernate not to use lazy instantiation of Location objects (in Location.hbm.xml)
<class name="Location" table="LOCATIONS" lazy="false"> ... </class>
id 101 102
city
province
result = (Location)session.load(Location.class,id);
tx.commit(); } catch (ObjectNotFoundException e) { logger.info("Object not found. id = "+id, e); if ( tx != null && ! tx.wasCommitted() ) tx.rollback(); } catch (HibernateException e) { logger.error("Hibernate exception", e); if ( tx != null && ! tx.wasCommitted() ) tx.rollback(); } finally { if ( session != null && session.isOpen() ) session.close(); } return result;
}
Details of findByName( )
Exercise
Details of save
Exercise
Redundant Code
public Location findById( int id ) { try { beginTransaction( ); do the work here commitTransaction( ); } catch (ObjectNotFoundException e) { handleError( e ); } catch (HibernateException e) { handleError( e ); } finally { if ( session != null && session.isOpen() ) session.close(); }
public boolean save( Location location ) { boolean result = false; ... try { beginTransaction( ); session.saveOrUpdate( location ); commitTransaction( ); } catch ( ... ) { handleException( e ); } finally { ... } return result; }
LocationDao
EventDao
SpeakerDao
AbstractDao.save
protected Object save( Object obj ) { Object result = null; try { beginTransaction(); result = session.saveOrUpdate( obj ); commitTransaction();
} catch (ObjectNotFoundException e) { handleError( e ); } catch (HibernateException e) { handleError( e ); } finally { closeSession( ); }
return result; }
AbstractDao.load
protected Object load( Class clazz, Serializable id ) { Object result = null; try { beginTransaction(); result = session.load( clazz, id); commitTransaction()
} catch (ObjectNotFoundException e) { handleError( e ); } catch (HibernateException e) { handleError( e ); } finally { closeSession( ); }
return result; }
Exercise
use your SimpleLocationDao to write a layer superclass named AbstractDao. write a LocationDao that extends AbstractDao
Hibernate queries you Hibernate Query Language (HQL). HQL is object-centric - use class and property names, not SQL table names.
HQL example
Problem: Find all events which are held at Kasetsart HQL:
String query = "select e from Event e where e.location.name = 'Kasetsart University'"; Query q = session.createQuery( query );
Many-to-one Associations
public class Event { private long id; private String name; private Location location; // 1-to-many assoc. private Date startDate; private long duration; public Event( ) { } ... }
Learning Hibernate
Tutorial at www.hibernate.org Another good tutorial: http://www.allapplabs.com/hibernate/hibernate_tutorials .htm Peak & Heudecker, Hibernate Quickly, 2006. Baur & King, Java Persistence with Hibernate, 2007, update of Hibernate in Action, and much longer. Baur & King, Hibernate in Action, 2005, considered the best Hibernate book, by one of the Hibernate creators.
Hibernate Tools
Hibernate Tools Eclipse plugin - HibernateConsole and more
Middlegen - generates class mapping files (hbm.xml) from an existing database schema. Has Eclipse plugin. Hibernate Synchronizer - generates class mapping files (hbm.xml) and Java classes from a database schema. hbm2ddl - creates a database schema (in SQL) from a hbm.xml file. hbm2java - creates a Java class from a hbm.xml file.