Integrating JDBC with Hibernate
from http://www.informit.com/guides/content.aspx?g=java&seqNum=575
Last updated Jun 25, 2010.
One
of the powerful things about Hibernate is that you do not typically
need to manually write SQL: you build a domain model that represents
your data model in an object-oriented manner and then interact with your
domain model. This is the ideal, but sometimes you need to model a
legacy data model or a data model that is not object-oriented in nature,
which leads to either complicated Hibernate mappings or the inclusion
of manual SQL. When this occurs, you do not want to have to build
separate data access object classes but rather you would like to find a
way to seamlessly integrate SQL into your existing data access object
classes in a way that your consumers do not even realize that you're not
using Hibernate Query Language (HQL) under-the-hood.
Fortunately you do not need to jump through too many hoops to
integrate manual JDBC into your Hibernate classes, you just need to
perform the following steps:
- Obtain access to your Hibernate's Session object
- Create a class that implements org.hibernate.jdbc.Work, or
create an anonymous inner class that implements the Work interface, and
implement the execute() method using the supplied Connection object to
execute your SQL
- Pass the Work class to Hibernate's doWork() method, which in turn invokes your Work's execute() method
Listings 1 and 2 illustrate how to use the Work interface to execute a simple SQL statement.
Listing 1. MyDao.java
...
public class MyDao
{
...
public String getValue( long id )
{
// Create a SQL order of work, which we will use to execute a manual SQL statement
MyWork myWork = new MyWork( id );
// Gain access to the underlying Hibernate session
Session session = getSessionFactory().openSession();
// Ask the Hibernate session to execute the unit of work
session.doWork( myWork );
// Obtain the results of the unit of work
return myWork.getValue();
}
..
}
Listing 1 defines a getValue() method that accepts an id and returns a String. It creates a new MyWork instance, passing it the id as an initialization parameter, locates a Hibernate Session, and passes the MyWork instance to the Sessions doWork() method. After the query is complete, it retrieves the value from the MyWork class.
The mechanism that you use to obtain a Hibernate Session will be
dependent on the technology with which you are building your data access
object. If you're using Spring by extending HibernateDaoSupport, you can invoke getSessionFactory().openSession() to create a new Session object.
Listing 2 shows the source code for the MyWork class.
Listing 2. MyWork.java
public class MyWork implements Work
{
private long id;
private String value;
public MyWork( long id )
{
this.id = id;
}
public String getValue()
{
return value;
}
@Override
public void execute( Connection connection ) throws SQLException
{
PreparedStatement ps = null;
ResultSet rs = null;
try
{
ps = connection.prepareStatement( "SELECT * FROM table WHERE id = ?" );
ps.setLong( 1, id );
rs = ps.executeQuery();
while( rs.next() )
{
value = rs.getString( 1 );
}
}
catch( SQLException e ) { }
finally {
if( rs != null )
{
try {
rs.close();
}
catch( Exception e ) {}
}
if( ps != null )
{
try {
ps.close();
}
catch( Exception e ) {}
}
}
}
}
The MyWork class implements its data access logic in its execute() method. The execute() method is passed a java.sql.Connection object that you can use as you normally would to create a Statement, PreparedStatement, or CallableStatement. The doWork() method returns void, so it is up to you to develop a mechanism to return a value from your unit of work.
If you are executing SQL from which you do not necessarily need to
retrieve results, you can accomplish the same results by creating an
anonymous inner class:
// Gain access to the underlying Hibernate session
Session session = getSessionFactory().openSession();
// Ask the Hibernate session to execute the unit of work
session.doWork( new Work() {
@Override
public void execute( Connection connection ) {
// Implement your SQL here
}
} );
In this example we create the Work() implementation in the doWork()
method invocation and override the execute() method. Depending on your
background this might look a bit strange, but once you get used to it,
this is a fairly elegant way to implement your solution because it
reduces the number of explicit classes you need to create and it couples
the logic being executed with the invocation of that logic. For
complicated cases you want to loosely couple things, but for a SQL
statement it is overkill to create additional classes if you do not need
to. The challenge here, however, is that if you need to obtain results
from the query, you're limited because the doWork() method returns void.
Hibernate offers a simple mechanism to execute SQL inside your
Hibernate data access object classes by defining a unit of work and
passing it to your Hibernate Session's doWork() method. You can define your unit of work explicitly by creating a class that implements org.hibernate.jdbc.Work or by creating an anonymous inner class that implements the Work
interface on-the-fly. The best solution, if you are building your
domain model from scratch, is to model your objects as simply as you can
(remember the KISS principle: keep it simple, stupid), but if you have
to create a domain model that does not lend itself easily to an
object-oriented representation then you can integrate manual SQL in this
manner.
posted on 2010-11-10 16:17
无声 阅读(870)
评论(0) 编辑 收藏 所属分类:
职场生活