25
Hibernate 3.0 Introduction........................................................2 Architecture........................................................2 Example:.......................................................... 2 Hibernate Query Language...........................................10 Understanding HQL Syntax......................................... 10 Clauses in the HQL are:........................................11 Aggregate functions are:.......................................11 Subqueries..................................................... 11 HQL from clause................................................ 11 Hibernate Select Clause........................................11 Hibernate Criteria Query Example...................................11 Hibernate & JNDI...................................................12 Hibernate Datasource Properties..................................13 Using Stored Procedures in Hibernate...............................14 Rules/limitations for using stored procedures....................15 Mapping SQL and Java data types....................................15 J2EE & Hibernate...................................................16 Transaction strategy configuration...............................16 Table : JTA TransactionManagers..................................16 Association Mappings...............................................18 One to one....................................................... 18 Scenario:...................................................... 18 Schema:........................................................ 18 Many to one...................................................... 19 Scenario:...................................................... 19 Hibernate Mapping:............................................. 19 Schema:........................................................ 19 One to many...................................................... 19 Scenario:...................................................... 19 Hibernate Mapping:............................................. 19 Schema:........................................................ 20 Collections of values..............................................20 Collection Elements.............................................. 20 Set............................................................ 21 Array.......................................................... 21 Map............................................................ 21 List........................................................... 21 Hibernate object states............................................22

Hibernate Kick Start

Embed Size (px)

Citation preview

Page 1: Hibernate Kick Start

Hibernate 3.0Introduction..............................................................................................................2Architecture.............................................................................................................2

Example:...............................................................................................................2Hibernate Query Language....................................................................................10

Understanding HQL Syntax.................................................................................10Clauses in the HQL are:...................................................................................11Aggregate functions are:.................................................................................11Subqueries.......................................................................................................11HQL from clause..............................................................................................11Hibernate Select Clause..................................................................................11

Hibernate Criteria Query Example.........................................................................11Hibernate & JNDI....................................................................................................12

Hibernate Datasource Properties........................................................................13Using Stored Procedures in Hibernate...................................................................14

Rules/limitations for using stored procedures....................................................15Mapping SQL and Java data types.........................................................................15J2EE & Hibernate....................................................................................................16

Transaction strategy configuration.....................................................................16Table : JTA TransactionManagers........................................................................16

Association Mappings.............................................................................................18One to one..........................................................................................................18

Scenario:..........................................................................................................18Schema:...........................................................................................................18

Many to one........................................................................................................19Scenario:..........................................................................................................19Hibernate Mapping:.........................................................................................19Schema:...........................................................................................................19

One to many.......................................................................................................19Scenario:..........................................................................................................19Hibernate Mapping:.........................................................................................19Schema:...........................................................................................................20

Collections of values..............................................................................................20Collection Elements............................................................................................20

Set...................................................................................................................21Array................................................................................................................21Map..................................................................................................................21List...................................................................................................................21

Hibernate object states..........................................................................................22Modifying persistent objects...............................................................................22Modifying detached objects................................................................................23

Introduction

Page 2: Hibernate Kick Start

It is an object-relational mapping(ORM) solution for the Java language. It provides an easy to

use framework for mapping an object-oriented domain model to a traditional relational

database.

Hibernate was developed by a team of Java Software Developers around the world

led by Gavin King.

Architecture

Example: Here is an example of using hibernate . But before that we need to download

the hibernate related files from hibernate.org and unzip them. Following jar

files are important and should be included with our application :

Page 3: Hibernate Kick Start

Step 1: Create a table as :

CREATE TABLE EMP (

EMPNO NUMBER (4) NOT NULL,

ENAME VARCHAR2 (10),

JOB VARCHAR2 (9)

CONSTRAINT PK_EMP

PRIMARY KEY ( EMPNO )

) ;

Step 2: Now write a persistent object or POJO (Plain Old Java Object)

public class Employee {

private int id;

private String empName;

private String empJob;

public int getId()

{

return id;

}

public void setId(int id)

Page 4: Hibernate Kick Start

{

this.id=id;

}

public String getEmpName()

{

return empName;

}

public void setEmpName(String name)

{

this.empName=name;

}

public String getEmpJob()

{

return empJob;

}

public void setEmpJob(String job)

{

this.empJob=job;

}

}

Step 3: Now write a mapping file ;this is nothing but an xml file .

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping>

<class name="Employee" table="EMP">

<id name="id" column="EMPNO" type="java.lang.Integer">

<generator class="sequence"/>

</id>

<property name="empName" type="java.lang.String" column="ENAME"/>

<property name="empJob" type="java.lang.String" column="JOB"/>

</class>

</hibernate-mapping>

Points to remember about the mapping file :-

Page 5: Hibernate Kick Start

class name should be mapped with the correct table.

<id> tag is used to map the primary key.

The id name and property name should have to be equivalent to the field of

our Persistant Object (in the above example our persistant object is class Employee so the id name and property name is equal to the field of Employee class).

Type: the java data type.

The <generator> element is used to specify the class name to be used to generate the primary key for new record while saving a new record.Here are the list of some commonly used generators in hibernate:

Generator Description

IncrementIt 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.

identity It supports identity columns in DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL. The returned identifier is of type long, short or int.

sequenceThe sequence generator uses a sequence in DB2, PostgreSQL, Oracle, SAP DB, McKoi or a generator in Interbase. The returned identifier is of type long, short or int

Hilo

The hilo generator uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int, given a table and column (by default hibernate_unique_key and next_hi respectively) as a source of hi values. The hi/lo algorithm generates identifiers that are unique only for a particular database. Do not use this generator with connections enlisted with JTA or with a user-supplied connection.

seqhiloThe seqhilo generator uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int, given a named database sequence.

uuidThe uuid generator uses a 128-bit UUID algorithm to generate identifiers of type string, unique within a network (the IP address is used). The UUID is encoded as a string of hexadecimal digits of length 32.

guid It uses a database-generated GUID string on MS SQL Server and MySQL.

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

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.

selectretrieves a primary key assigned by a database trigger by selecting the row by some unique key and retrieving the primary key value.

foreignuses the identifier of another associated object. Usually used in conjunction with a <one-to-one> primary key association.

Page 6: Hibernate Kick Start

Save the above file as Employee.hbm.xml.It's a good practise to give the name of your mapping file similar to the persistant class name.

Step 4: Create hibernate configuration file .

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

<!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<!-- Database connection settings -->

<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>

<property name="connection.url">jdbc:oracle:thin:@pc176:1521:OBODB</property>

<property name="connection.username">obo1</property>

<property name="connection.password">obopass1</property>

<!-- JDBC connection pool (use the built-in) -->

<property name="connection.pool_size">1</property>

<!-- SQL dialect -->

<property name="dialect">org.hibernate.dialect.OracleDialect</property>

<!-- Enable Hibernate's automatic session context management -->

<property name="current_session_context_class">thread</property>

<!-- Disable the second-level cache -->

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

<!-- Echo all executed SQL to stdout -->

<property name="show_sql">true</property>

<!-- Drop and re-create the database schema on startup -->

<property name="hbm2ddl.auto">create</property>

<!-- our mapping file name -->

<mapping resource="Employee.hbm.xml"/>

</session-factory>

</hibernate-configuration>

Save file as hibernate.cfg.cml.

Page 7: Hibernate Kick Start

In the above configuration file The dialect property is org.hibernate.dialect. OracleDialect which tells the Hibernate that we are using Oracle Database. Hibernate supports many database and provides dialect support for each. Few of them are.

● DB2 - org.hibernate.dialect.DB2Dialect

● MySQL - org.hibernate.dialect.MySQLDialect

● Oracle (any version) - org.hibernate.dialect.OracleDialect

● Oracle 9 - org.hibernate.dialect.Oracle9Dialect

● Sybase - org.hibernate.dialect.SybaseDialect

● Sybase Anywhere - org.hibernate.dialect.SybaseAnywhereDialect

The <mapping resource="Employee.hbm.xml"/> property is the mapping for our contact table.

The hbm2ddl.auto option turns on automatic generation of database schemas - directly into the

database. This can of course also be turned off (by removing the config option) or redirected to a

file with the help of the SchemaExport Ant task.

Step 5: Write code for the Hibernate Example.

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

public class FirstExample {

public static void main(String[] args) {

Session session = null;

try{

// This step will read hibernate.cfg.xml and prepare hibernate for use

SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

session =sessionFactory.openSession();

//Create new instance of Employee and set values in it by reading them from form object

System.out.println("Inserting Record");

Employee emp = new Emp();

emp.setId(640);

emp.setEmpName("ABC");

emp.setEmpJob("XYZ");

session.save(emp);

System.out.println("Done");

}catch(Exception e){

System.out.println(e.getMessage());

}finally{

// Actual emp insertion will happen at this step

Page 8: Hibernate Kick Start

session.flush();

session.close();

}

}

}

We have to startup Hibernate. This startup includes building a global SessionFactory object and to store it somewhere for easy access in application code. 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.

A SessionFactory is threadsafe, many threads can access it concurrently and request Sessions. A Session is a non-threadsafe object that represents a single unit-of-work with the database. Sessions are opened from a SessionFactory and are closed when all work is completed.

A SessionFactory is usually only build once, e.g. at startup with a load-on-startup servlet. This also means we should not keep it in an instance variable in your servlets, but in some other location. Furthermore, we need some kind of Singleton, so we can access the SessionFactory easily in application code. The approach shown next solves both problems: startup configuration and easy access to a SessionFactory.

We implement a HibernateUtil helper class:

import org.hibernate.*;

import org.hibernate.cfg.*;

public class HibernateUtil {

private static Log log = LogFactory.getLog(HibernateUtil.class);

private static final SessionFactory sessionFactory;

static {

try {

// Create the SessionFactory

sessionFactory = new Configuration().configure().buildSessionFactory();

} catch (Throwable ex) {

// Make sure we log the exception, as it might be swallowed

log.error("Initial SessionFactory creation failed.", ex);

throw new ExceptionInInitializerError(ex);

}

}

public static final ThreadLocal session = new ThreadLocal();

public static Session currentSession() {

Session s = (Session) session.get();

// Open a new Session, if this Thread has none yet

if (s == null) {

s = sessionFactory.openSession();

session.set(s);

Page 9: Hibernate Kick Start

}

return s;

}

public static void closeSession() {

Session s = (Session) session.get();

if (s != null)

s.close();

session.set(null);

}

}

This class does not only take care of the SessionFactory with its static initializer, but also has a ThreadLocal variable which holds the Session for the current thread.

The call to configure() loads the hibernate.cfg.xml configuration file and initializes the Configuration instance.

Hibernate Query Language Hibernate Query Language or HQL for short is extremely powerful query language. HQL is much like SQL and are case-insensitive, except for the names of the Java Classes and properties. Hibernate Query Language is used to execute queries against database. Hibernate automatically generates the sql query and execute it against underlying database if HQL is used in the application. HQL is based on the relational object models and makes the SQL object oriented. Hibernate Query Language uses Classes and properties instead of tables and columns. Hibernate Query Language is extremely powerful and it supports Polymorphism, Associations, Much less verbose than SQL.

There are other options that can be used while using Hibernate. These are Query By Criteria (QBC) and Query BY Example (QBE) using Criteria API and the Native SQL queries.

Understanding HQL SyntaxAny Hibernate Query Language may consist of following elements:

Clauses

Aggregate functions

Subqueries

Clauses in the HQL are:

from

select

where

order by

group by

Page 10: Hibernate Kick Start

Aggregate functions are:

avg(...), sum(...), min(...), max(...)

count(*)

count(...), count(distinct ...), count(all...)

Subqueries

Subqueries are nothing but its a query within another query. Hibernate supports Subqueries if the underlying database supports it.

HQL from clause

List list = session.createQuery("from Employee").list();

Hibernate Select Clause

String query = "SELECT id,empName,empJob from Employee";

List list = session.createQuery(query).list();

Note : We have to specify the field name and the persistant class name with the SELECT clause.

Similarly we can apply WHERE,ORDER BY,GROUP BY clause.

Hibernate Criteria Query Example The Criteria interface allows to create and execute object-oriented queries. It is powerful alternative to the HQL but has own limitations. Criteria Query is used mostly in case of multi criteria search screens, where HQL is not very effective.

The interface org.hibernate.Criteria is used to create the criterion for the search. The org.hibernate.Criteria interface represents a query against a persistent class. The Session is a factory for Criteria instances. Here is a simple example of Hibernate Criterial Query:

To retrieve list of all employees

List list = session.createCriteria(Employee.class).list();

Conditions placed on retrieving data are known as criterion. The Criterion class is the object-oriented representation of the relational criterion. It can be used as restrictions on the criteria query. In other words, Criterion is the object-oriented representation of the "where" clause of a SQL query. The conditions to be applied (also known as restrictions) can be provided by the Restrictions class. In code this would be:

Criterion crit=Restriction.eq(orderId,OD00009);criteria.add(crit);

From the above example it is clear that the Criterion is the "where" clause, which, when added to the Criteria object, provides a complete query with restrictions.Here the built-in Restriction type eq() (for testing equality) is being used.

The Projection class is an object-oriented representation of query resultset projection in a Criteria query. In simpler terms, projection refers to the fields mentioned in the select clause of a query. The same can be achieved by using the Projection class in a Criteria query. The Projection class acts as a factory for the Projection class. Projection can be added by using the addProjection()

Page 11: Hibernate Kick Start

method of the ProjectionList class. The addProjection() method of the Criteria class in turn returns a Criterion object. In code this would be:

List products=session.createCriteria(Product.class)

. setProjection(Projection.property(\"name\"))

.list();

The Order class represents the "order by" clause of SQL. By using the asc() and desc() methods of this class, order can be imposed upon the Criteria resultselt. Restriction means imposing conditions. To retrieve data based on certain conditions, Restriction must be used. Here the Restriction class comes into the picture. All the conditions provided by SQL are available in Criteria. The ones most commonly used are as follows:

Restriction.between is used to apply a "between" constraint to the field.

Restriction.eq is used to apply an "equal" constraint to the field.

Restriction.ge is used to apply a "greater than or equal" constraint to the field.

Restriction.gt is used to apply a "greater than" constraint to the field.

Restriction.idEq is used to apply an "equal" constraint to the identifier property.

Restriction.in is used to apply an "in" constraint to the field.

List orders = session.createCriteria(Order.class)

.setFetchMode(“products”,FetchMode.JOIN)

.add(Restrictions.eq(“id”,”1111”))

.list();

Hibernate & JNDI

For use inside an application server, we should almost always configure Hibernate to obtain connections from an application server Datasource registered in JNDI. We need to set at least one of the following properties:

Hibernate Datasource Properties

Propery name Purpose

connection.datasource datasource JNDI name

Jndi.url URL of the JNDI provider (optional)

Jndi.class class of the JNDI InitialContextFactory (optional)

Property name “connection.datasource” is must and it must be written in our “hibernate.cfg.xml” file; rest two properties are optional.

Here is how i have written my hibernate.cfg.xml file :

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

<!DOCTYPE hibernate-configuration PUBLIC

Page 12: Hibernate Kick Start

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<property name="jndi.url">t3://localhost:7080</property>

<property name="jndi.class">weblogic.jndi.WLInitialContextFactory</property>

<property name="connection.datasource">jdbc/obodb_NonXA_ds</property>

<!-- JDBC connection pool (use the built-in) -->

<property name="connection.pool_size">1</property>

<!-- SQL dialect -->

<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>

<!-- Enable Hibernate's automatic session context management -->

<property name="current_session_context_class">thread</property>

<!-- Disable the second-level cache -->

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

<!-- Echo all executed SQL to stdout -->

<property name="show_sql">true</property>

<!-- Drop and re-create the database schema on startup -->

<!-- <property name="hbm2ddl.auto">create</property>-->

<mapping resource="employee.hbm.xml"/>

</session-factory>

</hibernate-configuration>

Using Stored Procedures in Hibernate Hibernate 3 introduces support for queries via stored procedures. The stored procedures must return a resultset as the first out-parameter to be able to work with Hibernate.

Mapping file:

Page 13: Hibernate Kick Start

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping>

<class name="Employee" table="EMP">

<id name="id" column="EMPNO" type="java.lang.Integer">

<generator class="sequence"/>

</id>

<property name="empName" type="java.lang.String" column="ENAME"/>

<property name="empJob" type="java.lang.String" column="JOB"/>

</class>

<sql-query name="selectAllEmployees_SP" callable="true">

<return alias="emp" class="Employee">

<return-property name="id" column="EMPNO"/>

<return-property name="empName" column="ENAME"/>

<return-property name="empJob" column="JOB"/>

</return>

{ ? = call selectAllEmployee() }

</sql-query>

</hibernate-mapping>

stored procedures currently only return scalars and entities. <return-join> and <load-collection> are not supported.

Rules/limitations for using stored proceduresTo use stored procedures with Hibernate the procedures have to follow some rules. If they do not follow those rules they are not usable with Hibernate. If we still want to use these procedures we have to execute them via session.connection(). The rules are different for each database, since database vendors have different stored procedure semantics/syntax.

Stored procedure queries can't be paged with setFirstResult()/setMaxResults().

Oracle rule:

• The procedure must return a result set. This is done by returning a SYS_REFCURSOR in Oracle 9 or 10. In Oracle we need to define a REF CURSOR type.

• Recommended form is { ? = call procName(<parameters>) } or { ? = call procName } (This is more an Oracle rule than a Hibernate rule.)

To use Stored Procedures with Hibernate we need to create a stored procedure first and then specify <sql-query> name inside the mapping file and call the procedure from mapping file and to use this query in our application use session.getNamedQuery(<sql-query name>).

Page 14: Hibernate Kick Start

Mapping SQL and Java data types

The following table shows the mapping between SQL and Java data types. They are from JDBC.

SQL data type Java data type

Simply mappable Object mappable

CHARACTER String

VARCHAR String

LONGVARCHAR String

NUMERIC java.math.BigDecimal

DECIMAL java.math.BigDecimal

BIT Boolean Boolean

TINYINT Byte Integer

SMALLINT Short Integer

INTEGER Int Integer

BIGINT Long Long

REAL Float Float

FLOAT Double Double

DOUBLE PRECISION Double Double

BINARY byte[]

VARBINARY byte[]

LONGVARBINARY byte[]

DATE java.sql.Date

TIME java.sql.Time

TIMESTAMP java.sql.Timestamp

J2EE & Hibernate

Transaction strategy configurationThe Hibernate Session API is independent of any transaction demarcation system in our architecture. If we let Hibernate use JDBC directly, through a connection pool, we may begin and end our transactions by calling the JDBC API. If we run in a J2EE application server, we might want to use bean-managed transactions and call the JTA API and UserTransaction when needed.

To keep our code portable between these two (and other) environments we recommend the optional Hibernate Transaction API, which wraps and hides the underlying system. we have to specify a factory class for Transaction instances by setting the Hibernate configuration property

Page 15: Hibernate Kick Start

hibernate.transaction.factory_class.

There are three standard (built-in) choices:

org.hibernate.transaction.JDBCTransactionFactory- delegates to database (JDBC) transactions (default)

org.hibernate.transaction.JTATransactionFactory- delegates to container-managed transaction if an existing transaction is underway in this context (e.g. EJB session bean method), otherwise a new transaction is started and bean-managed transaction are used.

org.hibernate.transaction.CMTTransactionFactory- delegates to container-managed JTA transactions

Some features in Hibernate (i.e. the second level cache, Contextual Sessions with JTA, etc.) require access to the JTA TransactionManager in a managed environment. In an application server we have to specify how Hibernate should obtain a reference to the TransactionManager, since J2EE does not standardize a single mechanism:

Table : JTA TransactionManagers

Transaction Factory Application Server

org.hibernate.transaction.JBossTransactionManagerLookup JBoss

org.hibernate.transaction.WeblogicTransactionManagerLookup Weblogic

org.hibernate.transaction.WebSphereTransactionManagerLookup WebSphere

org.hibernate.transaction.WebSphereExtendedJTATransactionLookup WebSphere 6

org.hibernate.transaction.JRun4TransactionManagerLookup JRun4

org.hibernate.transaction.BESTransactionManagerLookup Borland ES

CMT example below : // AccountBean Class

import java.rmi.RemoteException;

import java.util.List;

import javax.ejb.EJBException;

import javax.ejb.SessionBean;

import javax.ejb.SessionContext;

import org.hibernate.SQLQuery;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

public class AccountBean implements SessionBean {

private SessionContext context;

public AccountBean() {

super();

Page 16: Hibernate Kick Start

}

public void updateAccount(int accId) throws EJBException {

Session session = null;

SessionFactory sf = new Configuration().configure().buildSessionFactory();

session = sf.currentSession();

String query = "UPDATE ACCOUNT SET BALANCE=5000 WHERE ID="+accId;

SQLQuery sQuery = session.createSQLQuery(query);

sQuery.executeUpdate();

session.close();

}

}

//Hibernate configuration file : hibernate.cfg.xml.

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

<!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<property name="jndi.url">t3://localhost:7001</property>

<property name="jndi.class">weblogic.jndi.WLInitialContextFactory</property>

<property name="connection.datasource">jdbc/obodb_NonXA_ds</property>

<property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>

<property name="transaction.manager_lookup_class">org.hibernate.transaction.WeblogicTransactionManagerLookup</property>

<!-- Enable Hibernate's automatic session context management -->

<property name="current_session_context_class">jta</property>

<mapping resource="account.hbm.xml"/>

</session-factory>

Page 17: Hibernate Kick Start

</hibernate-configuration>

Association Mappings

One to oneIn this association one class holds a reference to a single instance of another class and they are related by a common PK.

Scenario:

Bar Foo.getBar() // returns corresponding Bar instance

Hibernate Mapping: In Hibernate, this could be mapped as follows:

<class name="Foo" table="foo"    ...    <one-to-one name="bar" class="Bar"/></class>

Schema:

Foo

Id

Bar

Id

Many to one

A many-to-one reference is analogous to a simple Java reference. It is the same as the one-to-one situation except there is no requirement to have a shared PK. Instead a FK is used.

Scenario:

Bar Foo.getBar() // returns corresponding Bar instance

Hibernate Mapping:

<class name="Foo" table="foo">     ...     <many-to-one name="bar" class="Bar" column="bar_id"/></class>

Page 18: Hibernate Kick Start

Schema:

Bar

Id

One to manyA one-to-many reference is basically a collection. Here a class, A, holds a reference to a collection of another class, B. The reverse of it results into Many to one association.

Scenario:

Set Foo.getBars() // returns corresponding Bar instance

Hibernate Mapping:

<class name="Foo" table="foo">    ...    <set role="bars" table="bar">        <key column="foo_id"/>        <one-to-many class="Bar"/>    </set></class>

Schema:

Foo

Id

Bar

Id foo_id

Collections of values Any collection of values or many-to-many association requires a dedicated collection table with a foreign key column or columns, collection element column or columns and possibly an index column or columns.

For a collection of values, we use the <element> tag inside appropriate collection node.

Foo

Id Bar_id

Page 19: Hibernate Kick Start

<element

column="column_name" (1)

formula="any SQL expression" (2)

type="typename" (3)

length="L"

precision="P"

scale="S"

not-null="true|false"

unique="true|false"

node="element-name"

/>

(1) column (optional): The name of the column holding the collection element values.

(2) formula (optional): An SQL formula used to evaluate the element.

(3) type (required): The type of the collection element.

Collection Elements

Set

<set name="names" table="person_names">

<key column="person_id"/>

<element column="person_name" type="string"/>

</set>

Array

An array of entities - in this case, a many to many association:

<array name="addresses"

table="PersonAddress"

cascade="persist">

<key column="personId"/>

<list-index column="sortOrder"/>

<many-to-many column="addressId" class="Address"/>

</array>

Map

A map from string indices to dates:

<map name="holidays"

Page 20: Hibernate Kick Start

table="holidays"

schema="dbo"

order-by="hol_name asc">

<key column="id"/>

<map-key column="hol_name" type="string"/>

<element column="hol_date" type="date"/>

</map>

List

A list of components (discussed in the next chapter):

<list name="carComponents"

table="CarComponents">

<key column="carId"/>

<list-index column="sortOrder"/>

<composite-element class="CarComponent">

<property name="price"/>

<property name="type"/>

<property name="serialNumber" column="serialNum"/>

</composite-element>

</list>

Hibernate object states Hibernate defines and supports the following 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. Use the Hibernate Session to make an object persistent (and let Hibernate take care of the SQL statements that need to be executed for this transition).

• 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. Developers don't execute manual UPDATE statements, or DELETE statements when an object should be made transient.

• Detached - a detached instance is an object that has been persistent, but its Session has been closed. The reference to the object is still valid, of course, and the detached instance might even be modified in this state. A detached instance can be reattached to a new Session at a later point in time, making it (and all the modifications) persistent again. This feature enables a programming model for long running units of work that require user think-time. We call them application transactions, i.e. a unit of work from the point of view of the user.

Page 21: Hibernate Kick Start

Modifying persistent objectsTransactional 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 our modifications persistent. So the most straightforward way to update the state of an object is to load() it, and then manipulate it directly, while the Session is open:

DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );

cat.setName("PK");

sess.flush(); // changes to cat are automatically detected and persisted

Sometimes this programming model is inefficient since it would require both an SQL SELECT (to load an object)

and an SQL UPDATE (to persist its updated state) in the same session. Therefore Hibernate offers an alternate

approach, using detached instances.

Modifying detached objectsMany applications need to retrieve an object in one transaction, send it to the UI layer for manipulation, then

save the changes in a new transaction. Applications that use this kind of approach in a high-concurrency environment usually use versioned data to ensure isolation for the "long" unit of work.

Hibernate supports this model by providing for reattachment of detached instances using the Session.

update() or Session.merge() methods:

// in the first session

Cat cat = (Cat) firstSession.load(Cat.class, catId);

Cat potentialMate = new Cat();

firstSession.save(potentialMate);

// in a higher layer of the application

cat.setMate(potentialMate);

// later, in a new session

secondSession.update(cat); // update cat

secondSession.update(mate); // update mate

If the Cat with identifier catId had already been loaded by secondSession when the application

Page 22: Hibernate Kick Start

tried to reattach it, an exception would have been thrown.Use update() if we are sure that the session does not contain an already persistent instance with the same identifier, and merge() if we want to merge our modifications at any time without consideration of the state of the session. In other words, update() is usually the first method we would call in a fresh session, ensuring that reattachment of our detached instances is the first operation that is executed.