Sie sind auf Seite 1von 68

OR Mapping with Hibernate

Persistence in OO Apps
In an object oriented application, persistence allows an
object to outlive the process that created it. The state of an object can be stored to a disc, and an object with the same state can be re-created at some point in future. Persistence Technologies:
JDBC JDO iBATIS TopLink EJB 2.1 Entity Beans

Why ORM?
We want to work with
objects having behavior, not rows and columns of data. Object-relational paradigm mismatch.
Presentation Tier

Business Tier
Java Developers

Persistence Tier
Object-relational paradigm mismatch

DB
DBAs

Paradigm Mismatch

The problem of Subtypes Problems related to Associations The problem of Identity The problem of Granularity Example- MegaMusic- an imaginary entertainment business
Artist
id firstName
artist

Concert
id title date venue

concert

lastName description concerts

artists

The problem of subtypes


Artist
id firstName lastName description concerts

Java supports type inheritance. A table in


SQL DB is not a type. SQL DB products dont support type of table inheritance. No polymorphic association.

Rock Artist
wishList genre guitarType drumType

So how does ORM help? Inheritance Mapping Table per class hierarchy Table per subclass Table per concrete class Also, with Hibernate, you can fire polymorphic queries

preferences

Association problems
OOPL represents associations using object references (HAS-A
relationship). In the relation world, associations are represented as foreign keys. Java relationships can be many-to-many. To represent many-to-many relationships btw two relations we need a join table which doesnt appear anywhere in the domain model. Artist
id firstName
artist

Concert
id

Artist_Concert
concert

title date

lastName description concerts

artist_id
artist

venue
artists

concert_id
concert

The problem of Identity


Identity of Java objects can be
expressed as: Object Identity (checked with ==) Object Equality (boolean equals(Object)) The identity of a DB row is expressed as the primary key value.

DB

JVM Heap

artist
artist

artist

Two objects which are


different in JVM heap can represent the same DB row.

The problem of Granularity


Concert
id title
concert

Granularity refers to the size of


the type youre working with. The domain model offers three levels of granularity: Concert Venue String Whereas, the relational DBs offer just two levels (next slide).

date artists venue

Venue
country state street zip

Granularity (contd.)
Concert
id

The relational DBs


Concert
id
title date artists
concert

title
concert

date artists

venue

offer just two levels: Table such as Concert and, Columns such as country, state .. What does OR Mapping Provide? Association Mappings

country state street zip

Venue
country state street zip

Persistence Implementation
There are various ways the persistence layer can be
implemented: Hard-coding with SQL/JDBC (more development and maintenance efforts are required) XML Persistence (just another text file; no capabilities for DB mgt. ) Using Object Serialization Other ORM Solutions (iBATIS, JDO, TopLink, JPA) EJB 2.1 Entity Beans.

Problems with Object Serialization

A serialized network of interconnected objects can only


be accessed as a whole; its impossible to retrieve any data from the stream without desterilizing the whole stream. Its impossible to access or update a single object or a subset of objects independently. Loading and overwriting an entire network of objects causes hits performance.

Hibernate vs. Entity Beans


EJB 2.1 Programming Model

EJB 2.1 Complex Programming Model


ejb-jar.xml

<<Home Interface>>

Boilerplate code
Entity Class

Needs heavyweight app server Persistence is not standardized

No support for Entity Inheritance


Hbernate Programming Model

Hibernate Entity classes are POJOs No dependency on API No EJB container required No XML required (use Java 5 Annotations)

POJO Beans

Mapping File (optional)

Robust support for Inheritance Mappings

Hibernate Benefits
Transparent & Declarative
Presentation Tier

Business Tier
Java Developers

Persistence Tier

Persistence Productivity Maintainability Performance Vendor Independence

Hibernate

Object-relational paradigm synchronization

DB
DBAs

Hibernate Goals
Do less work and have a happy DBA. No error prone JDBC code is required.
No manual handling of JDBC ResultSet No Object Conversion No hard coded SQL No Value Object Design Pattern No preexisting DB schema required No need to re-factor to support different DB vendors

Hibernate Mission Statement


Defining Transparent Persistence

Any class can be a persistent class. No interfaces have to be implemented. No persistent superclasses have to be extended.

Hibernate- The Big Picture

Java SE 1.4

Java SE 5.0

Entity Manager Hibernate Core XML Metadata Annotations Hibernate Core XML Metadata

Annotations- new Java language feature introduced in Java SE 5. Hibernate Annotations + Hibernate Entity Manager = EJB 3.0 JPA sub spec

Architecture

Architecture

SessionFactory

A thread-safe global object. Theres one SessionFactory per DB. Creating a SessionFactory is expensive to create. Factory for Sessions. Instantiated once!

Session

A single-threaded, short lived object representing conversation btw the app and the persistent store. A non-threadsafe object that performs a single unit of work. Wraps a JDBC connection. Acts as a factory for transactions. Is inexpensive to create!

Transaction

A single-threaded, short lived object that represents an atomic unit of work. Abstracts app from underlying JDBC transaction. A Session might span several Transactions in some cases.

First Hibernate Application


Following steps are involved in developing a Hibernate powered O/R mapping app: 1. Create POJO Bean (Entity Class) 2. Write Mapping File 3. Write Hibernate Configuration File 4. Prepare Hibernate Startup and Helper Class 5. Write the Client Code

Creating POJO Beans

Persistent classes are implemented as POJO beans. Not all instances of a persistent class are considered to
be in the persistent state - an instance may instead be transient or detached

POJO Programming Rules

Implement a no-argument constructor.



Provide a default constructor with at least package visibility. The no-argument constructor is required to instantiate an object of this class through reflection. Provide an identifier property (optional)

This property maps to the primary key column of a database table

POJO Programming Rules



Prefer non-final classes (optional)

Declare accessors and mutators for persistent fields (optional) Hibernate can also access fields directly, the benefit of accessor methods is robustness for refactoring

Mapping File

What is a 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.

Structure of a Mapping File


How does the Hibernate mapping file look like?

<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping3.0.dtd"> <hibernate-mapping> [...] </hibernate-mapping>

Structure of a Mapping File


Between the two hibernate-mapping tags, include a class

element. All persistent entity classes need such a mapping, to a table in the SQL database:
<hibernate-mapping package="com.ibm"> <class name="Employee" table="IBM_EMPLOYEE"> . </class> </hibernate-mapping>

Generating DB row Identifier

<id name="empid" column="EMP_ID"> <generator class="native"/> </id>

Persisting Class properties

<property name="empName" column="EMP_NAME" length="40" type="string" /> <property name="empDesg" column="EMP_DESG" type="string" /> <property name="salary" column="EMP_SAL" />

Mapping File

What should be the name of the mapping file?

The naming of mapping files can be arbitrary, however the hbm.xml suffix is a convention in the Hibernate developer community.

Mapping File

Where should be the mapping file located?


The mapping file should be present in the classpath.

This mapping file should be saved as Employee.hbm.xml, right in the directory next to the Employee Java class source file.

Mapping File

Where is the mapping file referred from?


All mapping files are referred from Hibernate configuration file

Hibernate Configuration

Whats the purpose of Hibernate configuration file?



Hibernate is the layer in your application which connects to this database, so it needs connection information. The connections are made through a JDBC connection pool, which we also have to configure.

Hibernate Configuration

Whats the name of Hibernate configuration file?



For Hibernate's configuration, we can use a simple hibernate.properties file, a slightly more sophisticated hibernate.cfg.xml file, or even complete programmatic setup. Most users prefer the XML configuration file:

Structure of Hibernate Configuration


<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC


"-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration3.0.dtd"> <hibernate-configuration> <session-factory>

</session-factory> </hibernate-configuration>

Structure of Hibernate Configuration

If you have several databases, use several <sessionfactory> configurations, usually in several configuration files (for easier startup). 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

Structure of Hibernate Configuration


Where should the configuration file placed? Copy the Hibernate configuration 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.

Hibernate Startup and Helper



Hibernate startup requires building a global SessionFactory object and to store it somewhere for easy access in application code. Well use a class that uses static singleton pattern.

Demo 1
Takeaway: Learn how to write a simple Hibernate Application

Hibernate_StartedApp

Object States

Detached

Persistent

GC

Transient

new

Object States
Transient - an object is transient if it has just been

instantiated using the new operator, and it is not associated with a Hibernate Session. It has no persistent representation in the database and no identifier value has been assigned. Transient instances will be destroyed by the garbage collector if the application doesn't hold a reference anymore.

Object States

Persistent - a persistent instance has a representation in the database and an identifier value. It might just have been saved or loaded, however, it is by definition in the scope of a Session. Hibernate will detect any changes made to an object in persistent state and synchronize the state with the database when the unit of work completes.

Object States

Detached - a detached instance is an object that has been persistent, but its Session has been closed. A detached instance can be reattached to a new Session at a later point in time, making it (and all the modifications) persistent again.

How to make Objects Persistent


Newly instantiated instances of a a persistent class are considered transient by Hibernate. We can make a transient instance persistent by associating it with a session and calling save(). Long generatedId = (Long) sess.save(fritz);

How to Load Persistent Objects

The load() methods of Session gives you a way to retrieve a persistent instance if you already know its identifier. load() takes a class object and will load the state into a newly instantiated instance of that class, in persistent state. Example

Cat fritz = (Cat) sess.load(Cat.class, generatedId);


Note that load() will throw an ObjectNotFoundException if there is no matching database row

Loading persistent objects with get()

If you are not certain that a matching row exists, you should use the get() method, which hits the database immediately and returns null if there is no matching row. Example:

Cat cat = (Cat) sess.get(Cat.class, id);


if (cat==null) { cat = new Cat();

sess.save(cat, id);
} return cat;

Load() vs. get()

If you are not certain that a matching row exists, you should use the get() method, which hits the database immediately and returns null if there is no matching row. The load() method, on the other hand, will not hit the DB if the object in question can be found in the persistent context. Else, itll throw an ObjectNotFoundException.

Re-loading Objects

It is possible to re-load an object and all its collections at any time, using the refresh() method

Modifying persistent objects

Transactional persistent instances (ie. objects loaded, saved, created or queried by the Session) may be manipulated by the application and any changes to persistent state will be persisted when the Session is flushed There is no need to call a particular method (like update(), which has a different purpose) to make your modifications persistent.

Session Flushing

From time to time the Session will execute the SQL statements needed to synchronize the JDBC connection's state with the state of objects held in memory. This process, flush, occurs by default at the following points before some query executions from org.hibernate.Transaction.commit() from Session.flush()

Reattaching Detached Objects

Modifying an object after the session is closed has no effect on it's persistence state in the DB, the object is Detached; you can reattach a detached object to a new session by calling update() on the detached object

Deleting persistent objects



Session.delete() will remove an object's state from the database. Of course, your application might still hold a reference to a deleted object. It's best to think of delete() as making a persistent instance transient.

Demo 2
Takeaway: Learn how to deal with the persistent state of an object

Hibernate_ObjectPersistence

Object Equality

The problem stems from differences between object identity in the virtual machine (VM) and object identity in the database. From different parts of a concurrent running application, you might have two objects on the heap even though the object state is pulled from a single tuple in a DB.

Overriding equals() and hasCode()

Hibernate guarantees equivalence of persistent identity (database row) and Java identity only inside a particular session scope. So as soon as we mix instances retrieved in different sessions, we must implement equals() and hashCode() if we wish to have meaningful semantics

equals() Implementation
public boolean equals(Object other) {

if (this == other) return true; if ( !(other instanceof Person) ) return false; final Person aPerson = (Person) other; if ( !aPerson.getFirstName().equals( this.getFirstName() ) ) return false; if ( !aPerson.getLastName().equals( this.getLastName() ) ) return false; return true;
}

Key Generation
<id name="id" column="ID">

<generator class="assigned" />


</id> The optional <generator> child element names a Java class used to generate unique identifiers for instances of the persistent class. assigned is the default strategy which lets the application to assign an identifier to the object before save() is called

Takeaway: Learn how to write a basic Hibernate mapping file Hibernate_BasicMappings

Mapping Id Field

Use id element Use generator subelement with class attribute, which specifies the key generation scheme <class name="Person"> <id name="id" type="int"> <generator class="increment"/> </id> </class>

Key Generation Scheme via class attribute

class=increment

It generates identifiers of type long, short or int that are


unique only when no other process is inserting data into the same table. It should not the used in the clustered environment. class=assigned Lets the application to assign an identifier to the object before save() is called. This is the default strategy if no

<generator> element is specified.


class=native It picks identity, sequence or hilo depending upon the capabilities of the underlying database.

Takeaway: Learn how generate primary keys in DB table Hibernate_IdGeneration

Composite Key

For a table with composite key, you can multiple properties with the <composite-id> tag in the mapping file. The persistent class must implement the Serializable marker interface and override equals() and hashCode() methods.

Takeaway: Learn how generate composite keys Hibernate_CompositeKey

Hibernate DAO

DAO pattern Separation of data access (persistence) logic from business logic Enables easier replacement of database without affecting business logic DAO implementation strategies Domain DAO interface and implementation Domain DAO concrete classes

Takeaway: Learn how to segregate Database access code with DAO pattern Hibernate_DAO

Property Join

With Hibernate, you can move some properties to a different table using <join table> element. Using the <join> element, it is possible to map properties of one class to several tables.

Configuring a Connection Pool

Code Snippet
<property name="c3p0.min_size">5</property> <property name="c3p0.max_size">20</property> <property name="c3p0.timeout">1800</property> <property name="c3p0.max_statements">50</property>

Das könnte Ihnen auch gefallen