Forum Controls
Spotlight Features

The Rich Engineering Heritage Behind Dependency Injection

Andrew McVeigh takes us on a tour of the rich heritage behind dependency injection, what it represents, and tells us why its here to stay.

NetBeans 6: Matisse Updates

NetBeans 6 delivers great updates to the Matisse GUI builder. Spend a few minutes with Roman Strobl and get an expert briefing on what's new and what has changed.

Introduction to Groovy Part 3

In this, the third and final installation of Andres' Introduction to Groovy series, you learn about how Groovy handles variable numbers of arguments, named parameters, currying, and more about Groovy operators. Including, some new operators.

Easier Custom Components with Swing Fuse

Swing Fuse (actually just Fuse), is a framework designed to make it easier to create your own custom desktop components. In this article, Daniel Spiewak shows you how to get started and provides sample source code you can download.

Benchmark Analysis: Guice vs Spring

Willam Louth shows how he uses JXInsight Probes to investigate probable performance issues with code bases that he is not familiar with. He also highlights possible pitfalls in creating a benchmark, as well as in the analysis of results.
Replies: 0 - Pages: 1  
Threads: [ Previous | Next ]
  Click to reply to this thread Reply

Hibernate: Providing Connections for Hibernate

At 10:56 PM on Apr 24, 2005, R.J. Lorimer wrote:

Hibernate, being an Object->Relational DB Mapper for Java, needs access to JDBC connections. Out of the box, Hibernate is fairly self contained when it comes to connection control. By default, Hibernate ships with the ability to obtain a data source implementation ( javax.sql.DataSource ) from JNDI by setting the properties appropriately:

hibernate.connection.datasource = java:/comp/env/jdbc/test

Alternatively, if JNDI isn't an option, you can use a Hibernate-internal connection pool implementation (C3PO), and simply give driver/url information for Hibernate to create and pool its own connections:

hibernate.connection.driver_class = org.postgresql.Driver
hibernate.connection.url = jdbc: postgresql://localhost/mydatabase
hibernate.connection.username = myuser
hibernate.connection.password = secret
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50

In both of these cases, it is the same process to get a Hibernate Session to work with:

Session session = sessionFactory.openSession();

Maybe neither of those are options will work for you. The data source implementation gives you control over the connections, but it requires JNDI availability. The connection pooling implementation doesn't require JNDI, but now Hibernate has it's own pool of connections, and you cannot gain access to them (well, you can, but it's a breach of the Hibernate API rules). Additionally, if you have a need to give Hibernate connections to use on a per-session basis, you can always ask the session factory for a session running on a particular connection:

Connection conn = // ... get connection from some outside source.
Session session = sessionFactory.openSession(conn);

This isn't always favorable, however, as you now have a lot of code interacting with your connection pool, and it may be potentially difficult (or even impossible) given your constraints to integrate your code to that level.

If you have legacy connection pooling or non-JNDI data sources that you need to get to, you can simply create an implementation of the Hibernate org.hibernate.connection.ConnectionProvider interface. The ConnectionProvider API is fairly straightforward, in consists of four methods:

  • configure(Properties) - This method tells the connection provider to prepare itself using the Hibernate properties passed in.
  • getConnection() throws SQLException - Get a method from your connection source for hibernate to use.
  • closeConnection(Connection) throws SQLException - Release a connection Hibernate has been using (potentilly putting it back in to your legacy pool, or whatever else).
  • close() - This method tells the connection provider to release any resources for shutdown.

Once implemented, it is simply a matter of telling Hibernate at configuration-time that you want it to use your connection provider:

hibernate.connection.provider_class=com.javalobby.tnt.MyConnectionProvider

The only problem you will have now is the fact that you don't have control over the instantiation of the connection provider implementation, and it needs to obtain access to your connection source at 'configure' time so that it can begin passing those connections to Hibernate. There are a couple of solutions, all of them based in static fields - straight static references, singletons, and thread-locals. It largely depends on your implementation what will work for you - I'll just address static references as they are the most simple, and most straightforward:

// configuring hibernate here.
Configuration configuration = new Configuration()
	.setProperty(Environment.CONNECTION_PROVIDER, "com.javalobby.tnt.MyConnectionProvider");
 
// providing reference to connection pool here.
LegacyConnectionPool legacyPool = getLegacyConnectionPool();
com.javalobby.tnt.MyConnectionProvider.connectionPool = legacyPool;
 
// Get the session factory 
// (this will invoke the construction of the connection provider, etc)
SessionFactory sessionFactory = configuration.buildSessionFactory();

Here is the implementation of the connection provider:

package com.javalobby.tnt;
 
import java.sql.*;
import java.util.*;
 
import org.hibernate.*;
import org.hibernate.connection.*;
 
public class MyConnectionProvider implements ConnectionProvider {
 public static LegacyConnectionPool connectionPool;
	
 public void configure(Properties props) throws HibernateException {
  if(connectionPool == null) {
   throw new HibernateException("Connection pool must be set.");
 }
 
 public Connection getConnection() throws SQLException {
  return connectionPool.getConnection();		
 }
 
 public void closeConnection(Connection conn) throws SQLException {
  connectionPool.freeConnection(conn);
 }
 
 public void close() {
 }
 
}

That's it!

Until next time,

R.J. Lorimer
rj -at- javalobby.org
http://www.coffee-bytes.com


thread.rss_message