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
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 :
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)
{
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 :-
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.
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.
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
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);
}
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
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()
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
"-//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:
<?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>).
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
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();
}
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>
</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>
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
<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"
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.
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
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.
Top Related