Hibernate Basics, Page 5
Inheritance is a fundamental concept of object-oriented languages. Through inheritance, objects can inherit the state and behavior of their ancestor, or superclass. The most common use of object inheritance in applications is to create a generic base type with one or more specialized subclasses. Persisting a class hierarchy can be difficult, since each hierarchy can have its own unique requirements.
To address the problems found in hierarchy persistence, Hibernate supports three different inheritance persistence strategies:
- Table per class hierarchy
- Table per subclass
- Table per concrete class
Each mapping strategy is incrementally more complicated. In the following sections, we‘ll discuss the first two inheritance strategies. We've never needed to use the third, and most complicated, strategy.
Table Per Class Hierarchy
This strategy is the most basic and easiest to use. All the classes in the hierarchy are stored in a single table. Suppose you have the base Event class, with ConferenceEvent and NetworkingEvent as subclasses. The mapping definition for this hierarchy is shown in listing 6.
Listing 6. Table per class hierarchy mapping
We've introduced a few new features in the mapping definition. The most important is the inclusion of the discriminator element. The discriminator column is what Hibernate uses to tell the different sub-classes apart when retrieving classes from the database. If you don't specify a discriminator value, Hibernate uses the object's class name. The discriminator element in the example mapping tells Hibernate to look in the event_type column for a string describing the class type.
The discriminator is only a column in the relational table-you don't need to define it as a property in your Java object.
The subclass element contains the properties and associations belonging to the subclass. Any association element is allowed between sub- class tags. You can't have an id element or a nested subclass element.
The table per class hierarchy strategy requires a single table, events, to store the three types of Event instances. Let's look at what our events table would look like with the table per hierarchy strategy, as shown in figure 3.
Figure 3: Table per hierarchy mapping
As you can see, one table contains the fields for all the objects in the hierarchy. The only obvious limitation is that your subclasses can‘t have columns declared as NOT NULL. Subclasses can't have non-null attributes because inserting the superclass, which doesn‘t even have the non-null attribute, will cause a null column violation when it‘s inserted into the database. The next inheritance strategy, table per sub-class, doesn't have this limitation.
Table Per Subclass
Instead of putting all the classes into a single table, you can choose to put each subclass into its own table. This approach eliminates the discriminator column and introduces a one-to-one mapping from the sub-class tables to the superclass table. The mapping definition for this strategy is shown in listing 7.
Listing 7. Table-per-subclass mapping
The joined-subclass element can contain the same elements as the subclass element. The key element contains the primary key associa-tion to the superclass, Event. Figure 4 shows the resulting relational schema.
Creating an association to an Event or one of its subclasses is a simple many–to–one element:
Figure 4: Table per subclass hierarchy
Since this association can refer to any class in the Event hierarchy, the association is referred to as a polymorphic association. You can also create a concrete association by giving the name of the specific subclass:
Persisting class hierarchies may seem like a complicated proposition, but Hibernate makes it fairly straightforward.
We've covered quite a bit of ground in this article. Starting with the most basic Hibernate configuration, we explored mapping file definitions and advanced configuration options.
As a persistence service, Hibernate operates in managed and nonmanaged environments. The configuration file, hibernate.cfg.xml, specifies how Hibernate obtains database connections-either from a JNDI DataSource or from a JDBC connection pool. Additionally, the map-ping definition files describing the persistent classes may be specified in the configuration file.
Mapping files provide Hibernate with the necessary information to persist objects to a relational database. Each persistent property of a class is defined in the mapping file, including collections and associations to other persistent objects. The mapping file also defines the mandatory primary key for persistent objects.
The primary key is defined using the id element. The id element provides the name of the object property, the column used to persist the primary key, and the strategy used to generate the primary key value. Hibernate supports 10 generator strategies, including the assigned strategy that lets you assign a primary key value outside of Hibernate.
Once the configuration and mapping files are written, the Configuration object loads the files and is used to create a SessionFactory. The SessionFactory only needs to be initialized once and can be reused throughout the application. The SessionFactory creates instances of the Session interface. Session instances are basically database connections with some additional functionality.
The Session interface is the primary developer interface to Hibernate. Using it, you can persist transient objects and make persistent objects transient. It also provides querying capabilities and transaction support. Unlike the SessionFactory, Session instances should not be reused throughout the application. Instead, a new Session instance should be obtained for each transaction.
Additional pluggable components supported by Hibernate include database connection pool services, transaction management, and object caching services. These components can improve performance by reusing or caching objects and improving transaction management.
Hibernate is flexible enough to be used in any Java application environment. In this article, we examined how to configure it to support application persistence in managed and nonmanaged environments, as well as how to create the SessionFactory and persist objects.
About the Author
Patrick Peak is the chief technology officer of BrowserMedia, a Java/J2EE web development/design firm in Bethesda, MD. His focus is on using open source frameworks/tools as a competitive advantage for rapid custom software development. He has been using Hibernate in numerous production applications for almost two years. He runs a Java/Technology weblog at www.patrickpeak.com.
Nick Heudecker is the president and founder of System Mobile, a software consulting firm headquartered in Chicago, IL. He has more than nine years of commercial development experience, and he has developed software products and solutions for multiple Fortune 500 clients as well as media, lobbying, and government organizations.
Source of This Material
By Patrick Peak and Nick Heudecker