Hibernate for Java SEby Jason Lee
By now it's easy to see that Hibernate is quickly becoming a popular (if not the most popular) O/R mapper/data integration framework for J2EE. It offers a developer clear, concise, and powerful tools for working with relational databases in the enterprise. But what if you need outside access to those entities that are wrapped up in your J2EE web application? Do you develop separate, yet identical, entities to access your data? Or do you write additional web components to manage the internal access to your data?
At some point, these questions are bound to come up, and for me, it was when my company needed to upload records into our database from multiple vendors in multiple file formats. I thought about the approach I had always taken before, which was to write shell and SQL scripts (and even stored procedures) to upload the data. But because our data model is quite complex, I decided to leverage what existing entities, Spring DAOs, and services outside of our web app I could and develop a custom J2SE command-line data loader.
The Big Question: Should You?
Much of the documentation and many of the examples that exist for Hibernate today all revolve around using it in a container. Whether it's for a web app or in-house "fat app," there's usually a container involved. There's good reason for this. Containers are designed to include support for all sorts of features, such as transactions, threading, and security. Nowadays, these are required tools for developing mid-size and enterprise applications. But what should you do when you need access to your entities objects outside your container? Should you use your existing infrastructure and code, or come at the problem from a different angle, possibly with a different language altogether? Of course, there is no right answer, and for the rest of this article I will explain my approach, which was to reuse my existing entities/POJOs outside of my Spring container.
Scripting languages such as Perl, Python, Ruby, or even Tcl (yes, I've done this before) seem to have some advantages at first. A lot of the time, they're quick to hack up, easy to get initial results, and can bypass a lot of the underlying complexity of Hibernate. It's possible in just a few lines to make a connection to a database, select some results, and print them out to the screen or some log file. However, depending on your data model, things can (and usually do) get quite complicated. Say you have a person table that has a foreign key to an address table, and while inserting data, the address doesn't insert properly, which causes the person to not insert as well: a typical transactional issue. One could argue that it's not too hard to account for this in your scripting language du jour, just like in your main application. But the question remains: why should you? If this logic already exists in your application, why code it again? And since this probably won't be the only case, you will be duplicating work and logic and thusly introducing the possibility of errors, as well.
Some people, however, will see this as OK and use whatever tool they feel is best for that job. Maybe you already have some sort of separate infrastructure for reasons outside of programming. Maybe you upload and test your data on a separate database and after it passes various tests, it is then migrated to a production database. Or maybe your database maintenance is outsourced and you just send the files to your partner company and they take of the issues. In the end, there could be many other reasons not to use your existing Hibernate data layer--none of them right or wrong. But if you can and will use your existing code base outside of your app, then read on. I might be able to uncover a few tips and save you a few headaches in the process.
Once you have decided that it is OK to use your existing
Hibernate objects outside of your container, then the first thing
you'll have to do is to manage all of the configuration yourself. The
approach I will take for the rest of the article is via a
command line, standalone Java app. Since you probably already have
a Hibernate XML configuration file set up, you already know what
parameters are required, such as JNDI
DataSource name, entity
mapping files, and miscellaneous properties for logging SQL.
If you decide to use a command-line application, you will have to
figure out how to parse the XML file and add it to your new
configuration. While parsing an XML document is not impossible, it
can sometimes be a little side project in itself. Thus, I recommend
using a regular properties file. A properties file is pretty
straightforward and fairly easy to load up and get values from. The
following is an example of a minimal set of properties needed to
configure Hibernate (sans any entity mappings):
hibernate.dialect=net.sf.hibernate.dialect.PostgreSQLDialect hibernate.connection.driver_class=org.postgresql.Driver hibernate.connection.url=jdbc:postgresql://devserver/devdb hibernate.connection.username=dbuser hibernate.connection.password=dbpassword hibernate.query.substitutions yes 'Y'
As you can see, the above properties specify the database dialect,
the JDBC driver class, database server name, user name and
password, and whether or not to use query substitutions. Once you
have defined these and saved them in a hibernate.properties
file (which should reside in your classpath, by the way), they are
fairly easy to load up and hand off to the Hibernate