Hibernate simplifies inheritance mapping

Learn three easy-to-implement strategies to map class hierarchies

Hibernate is an object-relational mapping and persistence framework that provides a lot of advanced features, ranging from introspection to polymorphism and inheritance mapping. But mapping class hierarchies to a relational database model might prove somewhat difficult. This article covers three strategies that you can use in your everyday programming to easily map complex object models to relational database models.

Xavier Coulon (xavier.coulon@fr.ibm.com), E-business IT Specialist, IBM Business Consulting Services

Xavier CoulonXavier Coulon joined IBM France as an IT specialist six years ago and began with ERP consulting on various platforms. For the last two years, he has been working on large J2EE projects involving open source frameworks such as Struts and Hibernate. Contact Xavier at xavier.coulon@fr.ibm.com.



Christian Brousseau, J2EE Consultant

Christian BrousseauChristian Brousseau is a proud Canadian who has been developing software for a little more than 10 years. He made his debut doing a lot of Windows development (C++, Visual Basic, Microsoft Foundation Classes, ActiveX), moving on to Java projects when version 1.0 of the language came out. His expertise as a J2EE consultant gave him the great opportunity to move to France, where he has helped design, develop, and deploy major enterprise-scale J2EE projects. Contact Christian at cbrous@fr.ibm.com.



14 December 2004

Also available in Russian Japanese

Overview

Hibernate is a pure Java object-relational mapping and persistence framework that allows you to map plain old Java objects to relational database tables using XML configuration files. Using Hibernate can save a lot of development time on a project, since the whole JDBC layer is managed by the framework. This means that your application's data access layer will sit above Hibernate and be completely abstracted away from of the underlying data model.

Hibernate has a number of advantages over other similar object-relational mapping approaches (JDO, entity beans, in-house development, and so on): it's free and open source, it has achieved a good level of maturity, it's widely used, and it has a very active community forum.

To integrate Hibernate into an existing Java project, you'll need to walk through the following steps:

  1. Download the latest release of the Hibernate framework from the Hibernate Web site. (See the Resources section below for a link.)
  2. Copy the necessary Hibernate libraries (JAR files) to your application's CLASSPATH.
  3. Create the XML configuration files that will be used to map your Java objects to your database tables. (We'll describe that process in this article.)
  4. Copy the XML configuration files to your application's CLASSPATH.

You'll notice that you don't have to modify any Java objects to support the framework. Imagine, for instance, that you needed to somehow change a database table that your Java application used -- by renaming a column, for example. Once you'd changed the table, all you'd have to do to update your Java application would be to update the appropriate XML configuration file. You wouldn't need to recompile any Java code.

Hibernate Query Language (HQL)

Hibernate provides a query language called Hibernate Query Language (HQL), which is quite similar SQL. For those of you who prefer good old-fashioned SQL queries, Hibernate still gives you the opportunity to use them. But our supporting example will use HQL exclusively.

HQL is quite simple to use. You will find all the familiar keywords you know from SQL, like SELECT, FROM, and WHERE. HQL differs from SQL in that you don't write queries directly on your data model (that is, on your tables, columns, etc.), but rather on you Java objects, using their properties and relationships.

Listing 1 illustrates a basic example. This HQL code retrieves all Individuals whose firstName is "John."

Listing 1. Basic HQL Query
SELECT * FROM eg.hibernate.mapping.dataobject.Individual WHERE firstName = "John"

You can refer to the HQL reference material on the Hibernate Website if you want to learn more about HQL syntax (see Resources for a link).

XML configuration files

The core of Hibernate's functionality resides inside XML configuration files. These files must reside in your application's CLASSPATH. We placed them in the config directory of our sample code package (which you can download from Resources).

The first file that we'll examine is hibernate.cfg.xml. It contains information regarding your data source (DB URL, schema name, username, password, etc.) and references to other configuration files that will contain your mapping information.

The remaining XML files allow you to map Java classes against database tables. We will take a closer look at those files later, but it is important to know that their filenames follow the pattern ClassName.hbm.xml.


Our supporting example

In this article, we'll examine a basic example that illustrates how Hibernate works and puts to good use three different strategies under which you can use Hibernate to do your object-relational mapping. Our example application will be used by an insurance company that must keep legal records of all the property rights that its customers are insured for. We've provided the full source code with this article (see Resources); this code provides basic functionality from which you could build a full-fledged application, such as a Web or Swing application.

Our example assumes a classic use case for this kind of application. The user would provide the search criteria for any type of customer (individual, corporation, government agency, etc.), and would then be presented with a list of all customers matching the specified criteria -- even if these are different types of customers. The user could access a more detailed view of a specific customer from that same list.

In our application, a property right is represented by the Right class. A Right can either be a Lease or a Property. A Right is owned by a customer. To represent our customer, we'll use the generic class Person. A Person can either be an Individual or a Corporation. Of course, the insurance company must know the Estates to which those Rights are assigned. An Estate is a very generic term, you'll agree. So, we'll use the Land and Building classes to give our developers more comprehensive objects to work with.

From this abstract, we can develop the class model shown in Figure 1:

Figure 1. Complete Class Model
Complete Class Model

Our database model was designed to cover the three different strategies we'll discuss in this article. For the Right hierarchy, we'll use a single table (TB_RIGHT) and map to the correct class using the DISCRIMINATOR column. For the Person hierarchy, we'll use what we call a super table (TB_PERSON) that will share the same IDs with two other tables (TB_CORPORATION and TB_INDIVIDUAL). The third hierarchy (Estate) uses two different tables (TB_BUILDING and TB_LAND) linked by a foreign key defined by the combination of two columns (REF_ESTATE_ID and REF_ESTATE_TYPE).

Figure 2 shows the data model:

Figure 2. Complete data model
Complete data model

Setting up the database

Hibernate supports a wide variety of RDBMSs, and any of them should work with our sample. However, the sample code and the text of this article have been tailored for HSQLDB (see Resources for a link), a fully functional relational database written entirely in the Java language. In the sql directory of the sample code package, you will find a file named datamodel.sql. This SQL script will create the data model used in our example.

Setting up the Java project

Although you can always build and execute the sample code using the command line, you may want to consider setting up the project in an IDE for better integration. Within the sample code package, you'll find the following directories:

  • config, which contains all the sample's XML configuration files (mapping, Log4J, etc.)
  • data, which contains configuration files used by HSQLDB. You will also find a batch file named startHSQLDB.bat that you may use to launch the database.
  • src, contains all the sample's source code.

Be sure to copy the required Java libraries and XML configuration files to you application's CLASSPATH. The code needs only the Hibernate and HSQLDB libraries in order to compile and run properly. You can download these packages from the Resources section.


Strategy 1: One table per subclass (Persons)

In our first strategy, we'll look at how to map our Person hierarchy. You'll notice that the data model is very close to our class model. As a result, we'll use a different table for each class in the hierarchy, but all these tables must share the same primary key (we'll explain that in more detail momentarily). Hibernate will then use this primary key when it inserts new records into the database. It will also make use of this same primary key to perform JOIN operations when accessing the database.

Now we need to map our object hierarchy to our table model. We have three tables (TB_PERSON, TB_INDIVIDUAL, and TB_CORPORATION). As we mentioned above, they all have a column named ID as a primary key. It's not mandatory to have a shared column name like this, but it is considered good practice -- and it makes it a lot easier to read the generated SQL queries.

In the XML mapping file, shown in Listing 2, you'll notice that the two concrete classes are declared as <joined-subclass> inside the Person mapping definition. The XML element <id> is mapped to the primary key for the top-level table TB_PERSON, while the <key> elements (from each subclass) are mapped to the matching primary keys of the TB_INDIVIDUAL and TB_CORPORATION tables.

Listing 2. Person.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
  <class name="eg.hibernate.mapping.dataobject.Person" table="TB_PERSON" polymorphism="implicit">
    <id name="id" column="ID">
      <generator class="assigned"/>
    </id>
    <set name="rights" lazy="false">
      <key column="REF_PERSON_ID"/>
      <one-to-many class="eg.hibernate.mapping.dataobject.Right" />
    </set>
    <joined-subclass name="eg.hibernate.mapping.dataobject.Individual" 
  table="TB_INDIVIDUAL">
      <key column="id"/>
      <property name="firstName" column="FIRST_NAME" type="java.lang.String" />
      <property name="lastName" column="LAST_NAME" type="java.lang.String" />
    </joined-subclass>
    <joined-subclass name="eg.hibernate.mapping.dataobject.Corporation" 
  table="TB_CORPORATION">
      <key column="id"/>
      <property name="name" column="NAME" type="string" />
      <property name="registrationNumber" column="REGISTRATION_NUMBER" type="string" />
    </joined-subclass>
  </class>
</hibernate-mapping>

Saving a new instance of Individual form our Java code with Hibernate is pretty straightforward, as shown in Listing 3:

Listing 3. Saving a new instance of Individual
public Object create(Object object) {
  Session session = null;
  try {
    session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    session.save(object);
    session.flush();
    tx.commit();
    ...
}

In turn, Hibernate generates the two SQL INSERT requests illustrated in Listing 4. That's two requests for just one save().

Listing 4. SQL insertion queries
insert into TB_PERSON (ID) values (?)
insert into TB_INDIVIDUAL (FIRST_NAME, LAST_NAME, id) values (?, ?, ?)

To access an Individual from the database, simply specify the class name in your HQL query, as shown in Listing 5.

Listing 5. Invoke an HQL query
public Person findIndividual(Integer id) {
  ...
  session.find("select p from " + Individual.class.getName() + " as p where p.id = ?",
    new Object[] { id },
    new Type[] { Hibernate.INTEGER });	
  ...
}

Hibernate will then automatically perform the SQL JOIN to retrieve all the necessary information from both tables, as shown in Listing 6:

Listing 6. SQL SELECT query for an Individual
select individual0_.id as ID, individual0_.FIRST_NAME as FIRST_NAME55_, 
  individual0_.LAST_NAME as LAST_NAME55_ 
  from TB_INDIVIDUAL individual0_ 
  inner join TB_PERSON individual0__1_ on individual0_.id=individual0__1_.ID 
  where (individual0_.id=? )

Querying abstract classes

Hibernate returns a collection of the matching heterogeneous concrete subclasses automatically when an abstract class is queried. For example, if we query every Person from the database, Hibernate will return a list of Individual and Corporation objects.

However, when no concrete class is specified, Hibernate needs to perform an SQL JOIN, since it doesn't know which table to go through. Amongst all the retrieved table columns returned from the HQL query, an extra dynamic column will be returned as well. The clazz column is used by Hibernate to instantiate and populate the returned object. We call this class determination dynamic, as opposed to the method that we'll use in our second strategy.

Listing 7 shows how to query an abstract Person given its id property, while Listing 8 shows the SQL query automatically generated by Hibernate, including the table junctions:

Listing 7. HQL query in a find() method call
public Person find(Integer id) {
  ...
  session.find("select p from " + Person.class.getName() + " as p where p.id = ?",
    new Object[] { id },
    new Type[] { Hibernate.INTEGER });	
  ...
}
Listing 8. SQL SELECT query for any type of Person
select person0_.ID as ID0_,
  casewhen(person0__1_.id is not null, 1,  
  casewhen(person0__2_.id is not null, 2,  
  casewhen(person0_.ID is not null, 0, -1))) as clazz_0_, 
  person0__1_.FIRST_NAME as FIRST_NAME61_0_, 
  person0__1_.LAST_NAME as LAST_NAME61_0_, 
  person0__2_.NAME as NAME62_0_, 
  person0__2_.REGISTRATION_NUMBER as REGISTRA3_62_0_ 
  from TB_PERSON person0_ 
  left outer join TB_INDIVIDUAL person0__1_ on person0_.ID=person0__1_.id 
  left outer join TB_CORPORATION person0__2_ on person0_.ID=person0__2_.id 
  where person0_.ID=?

Strategy 2: One Table per class herarchy (Rights)

For our Right hierarchy, we'll use a single table (TB_RIGHT) to store the entire class hierarchy. You'll notice that the TB_RIGHT table possesses all the columns necessary to store every attribute of the Right class hierarchy. Values of the saved instances will then be saved in the table, leaving every unused column filled with NULL values. (Because it's full of "holes," we often call it a Swiss cheese table.)

In Figure 3, you will notice that the TB_RIGHT table contains an additional column, DISCRIMINATOR. Hibernate uses this column to automatically instantiate the appropriate class and populate it accordingly. This column is mapped using the <discriminator> XML element from our mapping files.

Figure 3. TB_RIGHT table content
TB_RIGHT table content

Simplicity tip

In very large projects, you will be confronted with complex class hierarchies with several levels of abstract classes. Fortunately, you won't have to specify the discriminator-value for abstract classes. You only need to specify it for the actual concrete classes that Hibernate will use.

Just as in the Person mapping file in Listing 2, in Listing 9 we map the abstract class (Right) and all its attributes. To map our two concrete classes (Lease and Property), we will use the <subclass> XML tag. This tag is pretty straightforward; it requires the name attribute just as the class tag requires the discriminator-value attribute. Hibernate will use the last attribute to identify the class it should to work with.

As you'll notice from the class diagram in Figure 1, discriminator is not an attribute of any Java class. In fact, it's not even mapped. It is simply a technical column shared between Hibernate and the database.

Listing 9. Right.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
  "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
  <class name="eg.hibernate.mapping.dataobject.Right" table="TB_RIGHT" polymorphism="implicit">
    <id name="id" column="ID">
      <generator class="assigned"/>
    </id>
    <discriminator>
      <column name="DISCRIMINATOR"/>
    </discriminator>
    <property name="date" column="DATE" type="java.sql.Date" />
    <many-to-one name="person" class="eg.hibernate.mapping.dataobject.Person" column="REF_PERSON_ID"/>
    <any name="estate"
         meta-type="string"
         id-type="java.lang.Integer">
      <meta-value value="LND" class="eg.hibernate.mapping.dataobject.Land"/>
      <meta-value value="BLD" class="eg.hibernate.mapping.dataobject.Building"/>
      <column name="REF_ESTATE_TYPE"/>
      <column name="REF_ESTATE_ID"/>          
    </any>
    
    <subclass name="eg.hibernate.mapping.dataobject.Property" discriminator-value="PRO"/>
    
    <subclass name="eg.hibernate.mapping.dataobject.Lease" discriminator-value="LEA">
      <property name="duration" column="DURATION" type="java.lang.Integer" />
     </subclass>
  </class>
</hibernate-mapping>

In the mapping file in Listing 9, you'll notice a many-to-one relationship between the Right and Person hierarchies, which is (naturally) the opposite of the one found in the Person hierarchy (one-to-many). Notice also the relationship between the Right and Estate hierarchies; we'll cover that relationship later in this article.

As with the first strategy, here Hibernate produces pretty effective SQL statements when accessing the database. When we query a concrete class, as shown in Listing 10, Hibernate filters on the discriminator value automatically -- a good thing, because it means that Hibernate reads only the appropriate columns for the specified class.

Listing 10. SQL query on a concrete class
select property0_.ID as ID, property0_.DATE as DATE, 
	property0_.REF_PERSON_ID as REF_PERS4_, property0_.REF_ESTATE_TYPE as REF_ESTA5_, 
	property0_.REF_ESTATE_ID as REF_ESTA6_ 
	from TB_RIGHT property0_ where property0_.DISCRIMINATOR='PRO'

Things get a little trickier when we query an abstract class. Because Hibernate doesn't know what specific class you're after, it has to read every column (including the discriminator column), then determine which class to instantiate and, finally, populate it. The discriminator then plays the same role as the clazz column of our first strategy. But this approach proves to be more static, since the class name is derived directly from the discriminator's value.

Listing 11. SQL query of (abstract) Right classes
select right0_.ID as ID, 
	right0_.DISCRIMINATOR as DISCRIMI2_, 
	right0_.DATE as DATE, right0_.REF_PERSON_ID as REF_PERS4_, 
	right0_.REF_ESTATE_TYPE as REF_ESTA5_, right0_.REF_ESTATE_ID as REF_ESTA6_, 
	right0_.DURATION as DURATION from TB_RIGHT right0_

Strategy incompatibilities

As defined in the DTD of the Hibernate mapping, the two first strategies described in this article are mutually exclusive, which means that they cannot be combined to map a single hierarchy.

Database model integrity

There is one major concern regarding this second strategy: in order for it to work, you must set all non-shared columns to NULLABLE. The resulting table may prove very difficult to work with, since developers typically rely on database constraints. (After all, a Lease with a duration set to NULL doesn't make much sense!)

One solution would be to use database-level checking constraints. Depending on the DISCRIMINATOR value, you can define a set of rules to implement, as shown in Listing 12. Of course, your database engine has to support this feature. Furthermore, since those constraints must be expressed in a single valid expression for all concrete classes and at the same time, it can become difficult to maintain as the hierarchy grows.

Listing 12. Data integrity constraint
alter table TB_RIGHT 
	add constraint CHK_RIGHT check(	
		(discriminant ='DPP' and date is null and duration is null)
	or	(discriminant ='DLM' and date is not null and duration is not null));

Strategy 3: One table per concrete class (Estates)

Our third and last strategy is probably the most imaginative of all: having one table per concrete class and none for the Estate abstract superclass. We'll rely on Hibernate to provide support for polymorphism. In the XML mapping file shown in Listing 13, you'll notice that only our two concrete classes (Building and Land) are mapped:

Listing 13. Estate.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
  "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
  <class name="eg.hibernate.mapping.dataobject.Land" table="TB_LAND" polymorphism="implicit">
    <id name="id" column="ID">
      <generator class="assigned"/>
    </id>
    <property name="description" column="DESCRIPTION" type="java.lang.String" />
    <property name="squareFeet" column="SQUARE_FEET" type="java.lang.Double"/>
  </class>

  <class name="eg.hibernate.mapping.dataobject.Building" table="TB_BUILDING" polymorphism="implicit">
    <id name="id" column="ID">
      <generator class="assigned"/>
    </id>
    <property name="description" column="DESCRIPTION" type="java.lang.String" />
    <property name="address" column="ADDRESS" type="java.lang.String"/>
  </class>
</hibernate-mapping>

Sharing ID values between tables

It is important not to have identical ID values shared between two tables that are mapped inside the same class hierarchy. If you do, Hibernate will return several different objects for the same ID. This may prove confusing for Hibernate -- and for you as well.

As you look at the mapping file in Listing 13, your first reaction might be to say, "Hey! This mapping is no different from the ones I use every day. There's no big deal here!" And you'd be right to think so. Actually, only one condition is needed for our third strategy: we need to specifically set the polymorphism attribute to implicit.

Even though the Estate class is nowhere to be found in our mapping file, it still exists in our class hierarchy. And, since our two mapped classes (Building and Land) inherit from Estate, we can use this abstract superclass in our HQL queries, as shown in Listing 14. Hibernate will then use introspection to identify the classes that extend this abstract class so that it can perform the appropriate SQL queries for each of the subclasses successively.

Listing 14. HQL query in a find() method call
public Estate find(Integer id) {
  ...
  List objects =
    session.find(
      "select e from " + Estate.class.getName() + " as e where e.id = ?",
        new Object[] { id },
        new Type[] { Hibernate.INTEGER });
  ...
}

To find the matching Estates given their ID, Hibernate has to submit the two queries in Listing 15 to the database.

Listing 15. SQL queries
select land0_.ID as ID, land0_.DESCRIPTION as DESCRIPT2_, land0_.SQUARE_FEET as SQUARE_F3_ 
from TB_LAND land0_ where (land0_.ID=? )

select building0_.ID as ID, building0_.DESCRIPTION as DESCRIPT2_, building0_.ADDRESS as ADDRESS 
from TB_BUILDING building0_ where (building0_.ID=? )

As we saw in our second strategy, there is a many-to-one relationship between the Right and Estate classes. In plain English, it goes something like this: "An Estate can refer to manyRights. But each Right can refer to only oneEstate." But from our data model's perspective, there is no unique table we can use to create our foreign key constraint, like the one between TB_RIGHT and TB_PERSON. This makes it virtually impossible for us to create a foreign key. Fortunately, Hibernate provides us with a very powerful XML mapping element, the <any> tag, the use of which is illustrated in Listing 16.

Listing 16. XML mapping of an any relationship
<any name="estate"
	meta-type="string"
	id-type="java.lang.Integer">
  <meta-value value="LND" class="eg.hibernate.mapping.dataobject.Land"/>
  <meta-value value="BLD" class="eg.hibernate.mapping.dataobject.Building"/>
  <column name="REF_ESTATE_TYPE"/>
  <column name="REF_ESTATE_ID"/>          
</any>

Disabling polymorphism

Classes whose polymorphism support is disabled (<class...polymorphism="explicit"...>) are excluded from queries targeting any of their superclasses.

Let's have a closer look at our new piece of mapping. Our virtual foreign key is based on two columns from the TB_RIGHT table. The first one (REF_ESTATE_TYPE) contains the discriminator string that will be used to map the appropriate class name. The second (REF_ESTATE_ID) is the column name from the other table's primary key. Using default settings, Hibernate will attempt to store the mapped class names in the first column, which may prove space-consuming and inefficient (especially if class names are changed during code refactoring). Thankfully, Hibernate provides a way to associate class names to string constants using the <meta-value> XML element. These constants serve the same purpose as the discriminators discussed in the second strategy. Once again, this feature involves only Hibernate and the database, and thus doesn't alter the class hierarchy.

Database model integrity

Although standard SQL does not allow referential constraints with multiple tables at the same time for the given column, it is still possible to add a trigger that would check that the data exists in the target table given the discriminator value it reads. However, such an integrity enforcement method may prove very difficult to maintain and may also decrease overall database performance.


Polymorphism -- to the extreme!

Here's one thing to keep in mind when using Hibernate's built-in polymorphism: you can retrieve a lot more information than you bargained for if you're not careful, provided that all classes are mapped with the polymorphism attribute set to implicit. Listing 17 illustrates a way to retrieve the entire database using a two-word HQL query.

Listing 17. HQL query
public List all() {
  ...
  List objects = session.find("from Object");
  ...
}

Pretty powerful, don't you think? Of course, not many of us would need (or want, for that matter) to retrieve the entire database with a single HQL query. This (nonsense) example's goal is aimed only at showing the power of implicit polymorphism. You can exploit this power to avoid useless and resource-consuming SQL queries sent to the database.


Conclusion

In this article, we tried to give you a fairly simple implementation example for three mapping strategies Hibernate provides. In retrospect, each strategy has its advantages and drawbacks:

  • For our first strategy (one table per subclass), Hibernate will read multiple tables each time an object is instantiated and populated. That operation can produce good results if your indexes are well defined and your hierarchy isn't too deep. If that is not the case, however, you may experience problems with overall performance.
  • For our second strategy (one table per class hierarchy), you'll have to define your integrity using check constraints. This strategy might become difficult to maintain as the number of columns increases over time. On the other hand, you may choose not to use such constraints at all and rely on your application's code to manage its own data integrity.
  • Our third strategy (one table per concrete class) has some mapping limitations, and the underlying data model can't use referential integrity, meaning that you're not using the relational database engine to its full potential. On the plus side, though, this strategy can be combined quite easily with the other two.

Regardless of the strategy you choose, always keep in mind that you don't need to alter your Java classes in the process, meaning that there is absolutely no link between your business objects and the persistence framework. It's this degree of flexibility that is making Hibernate so popular in object-relational Java projects.


Download

DescriptionNameSize
Code samplej-hibernate-source.zip24KB

Resources

  • The Hibernate site provides all the information you need regarding this powerful object persistence framework. You can download the Hibernate files you'll need to run the sample application from this site.
  • The HSQLDB database is a an open source, lightweight database written entirely using the Java language. You can download HSQLDB from this site and use it as the database for the sample application.
  • Check out Hibernate's HQL reference for complete documentation on Hibernate Query Language.
  • "Using Hibernate to persist your Java objects to IBM DB2 Universal Database," Javid Jamae and Kulvir Singh Bhogal (developerWorks, June 2003) provides a good introduction on mapping classes to database tables using Hibernate.
  • "Developing Hibernate applications for use with WebSphere Application Server," Sunil Patil (IBM WebSphere Developer Technical Journal, September 2004) provides step-by-step instructions on using Websphere Application Server's connection and transaction management when creating Hibernate applications.
  • "Hibernate your data," Davor Cengija (ONJava.com, January 2004) gives you all the basics of the Hibernate API and describes how to make good use of its mapping files.
  • Hibernate in Action, Christian Bauer and Gavin King (Independent Pub Group, 2004) is a theoretical and practical guide to object-relational mapping. It is written by the Hibernate team.
  • Hibernate: A Developer's Notebook, James Elliot (O'Reilly, 2004) is another great guide to Hibernate.
  • Find hundreds of articles about every aspect of Java programming in the developerWorks Java technology zone.
  • Browse for books on these and other technical topics.

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Java technology on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=32195
ArticleTitle=Hibernate simplifies inheritance mapping
publish-date=12142004