IBM Bluemix Application development in the cloud on a free trial!
Get started
Log In | Register
developerWorks Community
"My profile
"My communities
"Settings
"Log out
IBM
Technical materials Trial software Community
Search for developerWorks
developerWorks Russia Technical Materials Java Technology Articles
Hibernate simplifies inheritance transformation By learning three simplified (to execute) strategies for displaying class hierarchies.
Hibernate is an object relational memory management and stable framework that provides many additional features from introspection to polymorphism and inheritance transformation.
And converting a class hierarchy into a relational database model can be quite difficult.
This article describes three strategies that can be applied in daily programming to simplify the transformation of complex object models into relational database models.
Xavier Coulon, E business IT Specialist, IBM Business Consulting Services
Close [x]
Xavier Coulon joined IBM France as an IT specialist six years ago and started with ERP consulting on various platforms.
For the last two years, he has been working on large J2EE projects, including open source frameworks such as Struts and Hibernate.
You can contact him at: xavier.coulon@fr.ibm.com.
Christian Brousseau, J2EE Consultant
Close [x]
Christian Brousseau, a Canadian who has been working on software for a little more than a decade.
I started with numerous Windows developments (C++, Visual Basic, Microsoft Foundation Classes, ActiveX), switched to Java projects when the first version was released.
His competence as a J2EE consultant gave him an excellent opportunity to move to France, where he helped design, develop and deploy many J2EE projects for the systematization of enterprises.
You can contact him at: cbrous@fr.ibm.com.
14.12.2004
Contents Introduction A visual example of the Integration Service Strategy 1: One table per Subclass (Persons) Strategy 2: One table per Class hierarchy (Rights) Strategy 3: One table per specific class (Estates) Uploading Resources Comments
Introduction Hibernate has a number of advantages over other similar approaches to object relational management (JDO, data management components, internal program development, etc.): it is an accessible source program that has reached a high degree of maturity, it is widely used and actively discussed.
To integrate the Hibernate package into an existing Java project, you need to go through the following steps: Download the latest version of the Hibernate framework from the Hibernate Web site.
Copy the necessary Hibernate libraries (JAR files) to your CLASSPATH applications.
Create XML configuration files that will be used to convert your Java objects into database tables.
(We will describe this process in this article).
Copy the XML configuration files to your CLASSPATH applications.
You will see that you will not have to modify any Java object to support the basics.
Imagine, for example, that you need to change the database table that your Java application used - for example, rename a column.
All you need to do to modify your Java application (to change the table) is to change the corresponding XML configuration file.
You donot need to recompile Java codes.
The query language of the Hibernate Package (HQL)
Hibernate provides a query language called the Hibernate Query Language, similar to SQL.
For those of you who prefer the good old SQL queries, Hibernate still gives you the opportunity to use them.
We will use HQL exclusively in our examples.
You will find all the familiar keywords that you know from SQL, such as: SELECT, FROM and WHERE.
HQL differs from SQL in that you do not write queries directly in your data model (i.e. in tables, columns, etc.), but in Java objects, using their properties and relationships.
Listing 1 illustrates the main example.
This HQL code restores all Individual tables, where firstName is "John".
Listing 1.
The main HQL query is SELECT * FROM eg.
hibernate.mapping.
dataobject.
Individual WHERE firstName = "John"
You can refer to the HQL link on the Hibernate Website if you want to learn more about the HQL syntax The essence of the Hibernate functionality is XML configuration files.
These files should be located in your CLASSPATH application.
We have placed them in the directory of our package with sample codes The first file that we will consider is hibernate.ctg.xml.
It contains information corresponding to your data source (DB URL, schema name, username, password, etc.), and refers to other configuration files that will contain the information you need about the conversion.
Saved XML files allow you to convert Java classes independently of database tables.
Next, we will look at these files in more detail, but for now it is important to note that the file names are created according to the sample ClassName.hbm.xml.
In this article, we will look at a basic example that shows how Hibernate works and implements three different strategies with which you can use Hibernate for object relational transformation.
Our trial application will be used by an insurance company, which must preserve legal records with copyrights, which is guaranteed to buyers.
We provide the full source code of the program for this article (see Resources); this source program provides the main functions with which you can build a complete application, such as Web or Swing applications.
Our sample assumes a classic use for such types of applications.
The user can provide a search criterion for different buyers (individual, corporate, for government organizations, etc.), and then present a list of all buyers distributed according to a special criterion - even if the buyers belong to different groups.
The user can provide the buyer from this list with the opportunity for a more detailed review.
In our application, copyright is represented by the Right class.
Right can be either Lease or Property.
Right - the property of the buyer.
To designate our customer, we use the generalized Person class.
A Person can be either Individual (personal) or Corporation (corporate).
Of course, the insurance company must know the Estate (property) to which these Rights are attributed.
Estate is a very generalized element, you will agree.
Therefore, we will use the Land and Building classes to provide our developers with more understandable terms for their work.
Based on this paragraph, you can develop a class model, shown in Diagram 1: Diagram 1.
Full class model Our database model has been modeled to describe three different strategies, which we will discuss in this article.
For the Right hierarchy, we use one table (TB RIGHT) and convert it to the desired class using the DISCRIMINATOR column.
For the Person hierarchy, we use the so called super table (TB PERSON), which has the same ID as the other two tables (TB CORPORATION and TB INDIVIDUAL).
The third hierarchy (Estate) uses two different tables (TB BUILDING and TV LAND), connected by a foreign key defined by a combination of two columns (REF ESTATE ID and REF ESTATE TYPE).
Diagram 2 shows the database model: Diagram 2.
Full database model
To the beginning of the Integration Service, Install the database
Hibernate supports a wide variety of RDBMS, each of which can work according to our sample.
However, the sample code and the text of this article are adapted to HSQLDB (see Resources), a fully functional relational database written entirely in Java.
In the SQL Reference, you will find a file called datamodel.
sql.
This SQL text creates a model of the data used in our sample.
You can also always build and execute a sample code using the command line; you can consider installing the project in the IDE for better integration.
As part of the sample code package, you will find the following pointers: config, which contains XML configuration files of all samples (conversion, Log4J, etc.) data, which contains configuration files used by HSQLDB.
You can also find a batch file called startHSQLDB.a bat that can be used to start the database.
src, contains the source text of all samples.
Make sure that the necessary Java libraries and XML configuration files are copied to your application CLASSPATH.
The code only needs the Hibernate and HSQLDB libraries for proper translation and execution.
You can download these packages from the Resources section.
To start Strategy 1: One table per subclass (Persons) In our first strategy, we will look at how to transform the Person hierarchy.
You will notice that the data model is very close to our class model.
Therefore, we will use different tables for each class in the hierarchy, but all these tables must have the same key (we will explain this in more detail in due time).
Hibernate uses this initial key when new records are included in the database.
It can also use the same initial key to perform JOIN operations during database access.
Now we need to transform our object hierarchy.
We have three tables (TB PERSON, TB INDIVIDUAL and TB CORPORATION).
As we noted above, they all have a column named ID as the initial key.
It is not necessary to have a common column with this name, but it is considered a good practice - and also makes it much easier to read generated SQL queries.
In the transformation XML file shown in Listing 2, you can notice that two specific classes are defined as <joined subclass> inside the transform definition of Person.
The XML <id> element is converted to the initial key for the top level TB PERSON table, while the <key> elements (from each subclass) are converted to the corresponding initial 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>
By saving the new Individual form property, our Java code with Hibernate remains quite simple, as shown in Listing 3: Listing 3.
Saving the new Individual public Object create(Object object)table property { Session session = null; try { session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); session.save(object); session.flush(); tx.commit(); ... }
Hibernate, in turn, generates two SQL INSERT requirements, shown in Listing 4.
These are two requirements for only one save ( ).
Listing 4.
SQL insert queries insert into TB PERSON (ID) values (?) insert into TB INDIVIDUAL (FIRST NAME, LAST NAME, id) values (?,?, ?)
To access the Individual table from the database, you just need to define the class name in your HQL query, as shown in Listing 5.
Listing 5.
Activating the 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 automatically perform a SQL JOIN to restore all the necessary information from both tables, as shown in Listing 6: Listing 6.
SQL SELECT query to select Individual individual0_.id as ID, individual0_.FIRST NAME as FIRST NAME55_, individual0_.LAST NAME LAST NAME55_ as from INDIVIDUAL individual0_ TB TB inner join PERSON individual0__1_ on individual0_.id=individual0__1_.ID where (individual0_.id=? )
The Hibernate abstract Class query automatically outputs the entire class group when an abstract class is requested.
For example, if we query the Person table from the database, Hibernate outputs a list of objects of the Individual and Corporation tables.
However, when the abstract class is not specified, the Hibernate package needs to execute SQL JOIN, because it is not known which table needs to be passed through.
Along with the other columns of the restored table derived from the HQL query, an additional dynamic column will also be restored.
The clazz column is used by the Hibernate package to define and place the restored object.
We call this class distribution dynamic, as opposed to the method that we will use in our second strategy.
Listing 7 shows how a Person is queried via id, while Listing 8 shows an SQL query automatically generated by Hibernate, including table crossing.
Listing 7.
HQL query in the search method of calling 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 in the Person table 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 REGISTRA3_62_0_ as TB from 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=?
At the beginning of Strategy 2: One table per Class Hierarchy (Rights) For our Right hierarchy, we use one table (TB RIGHT) to maintain the full class hierarchy.
You will notice that the TB RIGHT table has all the necessary columns to store all the properties of the class hierarchy of the Right table.
The values of the saved properties will then be saved in the table, each unused column will be filled with a null value.
(Because there are many "holes" in the table, we often call it "Swiss Cheese").
In Scheme 3, you will see that the TB RIGHT table includes an additional column to automatically determine the corresponding class and distribution according to the class.
This column is converted using the <discriminator> XML element from our conversion files.
Scheme 3.
The content of the TB RIGHT table is the height of simplicity In very large projects, you will encounter a complex class hierarchy consisting of several levels of abstract classes.
Fortunately, you donot have to specify the discriminator value for an abstract class.
You just need to define it for specific classes that Hibernate will use.
Just like in the Person conversion file in Listing 2, and in Listing 9, we will convert the abstract class (Right) and all its properties.
To convert our two specific classes (Lease and Property), we use the XML attribute <subclass>.
This attribute is quite simple; it requires the name property, just as the class attribute requires the discriminator value property.
Hibernate uses the latter property to define the class it should work with.
As you noticed from the class diagram in Diagram 1, discriminator is not a property of any Java class.
In fact, it is not even converted.
This is just a technical column placed 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 conversion file of Listing 9, you see the "set to unit" relationship between the Right and Person hierarchies, which (naturally) are the opposite of the relationships in the Person hierarchy ("unit to plurality").
Pay attention also to the relations between the Right and Estate hierarchies; later in this article we will look at these relations as well.
As in the first strategy, here Hibernate produces fairly efficient SQL statements when accessing the database.
When we request a specific class, as shown in Listing 10, Hibernate automatically filters using discriminator tools - good quality, because this means that Hibernate reads only the columns corresponding to the specified file.
Listing 10.
SQL query of a specific select class 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'
Everything is much more complicated when we request an abstract class.
Because Hibernate doesnot know which specific class is needed, it has to read each column (including the discriminator column), then it determines which class to isolate and, in the end, shows it.
The discriminator plays the same role as the clazz column in our first strategy.
But this is a match it turns out to be more static, while the class name is derived directly from the discriminator value.
Listing 11.
SQL query of (abstract) classes Right 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_
Incompatibility of strategies As defined by the DTD (document Type Definition) of the Hibernate transformation, the first two strategies described in this article are mutually exclusive.
This means that they cannot be combined when converting the same hierarchy.
There is one thing about these two strategies: in order for them to work, you need to "reset" all unused columns.
The resulting table can be difficult to work with, while developers usually rely on the integrity constraint in the database.
(After all, Lease with a value reduced to zero does not make any sense!)
The solution may be to use the integrity constraint of the database level check.
Depending on the properties of the discriminator, you can define a set of rules to execute, as shown in Listing 12.
Of course, the structure of your database should support this feature.
Moreover, since this integrity constraint must be expressed in one form for all specific classes, at the same time, with the growth of the hierarchy, it will be difficult to maintain it.
Listing 12.
Database integrity restriction 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));
At the beginning of Strategy 3: One table per specific class (Estates) Our third and final strategy is probably the most sophisticated of all: one table for a specific class and none for an abstract Estate superclass.
Let's use Hibernate to implement polymorphism support.
In the XML conversion file in Listing 13, you will see that only two of our specific classes have been converted (Building and Land): 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>
Separating Property IDs between tables is important so that there are no identical property IDs distributed between two tables that are transformed within the same class hierarchy.
If this happens, Hibernate outputs several different objects to the same ID.
This may be problematic for Hibernate - however, as well as for you.
If you look at the conversion file in Listing 13, your first reaction will be: "This conversion is no different from the ones I use every day.
Nothing special!"
And you will be right.
In fact, our third strategy requires only one condition: we need to establish the properties of polymorphism in an implicit way in a special way.
Despite the fact that the class Estate, it is impossible to find anywhere else to find your file conversion, it still exists in our class hierarchy.
And since our two converted class (Building and Land) is derived from the Estate, we can use this abstract superclass in our HQL queries, as shown in Listing 14.
Hibernate will use introspection to determine the classes that extend this abstract class so that it can successfully execute appropriate for each superclass SQL queries.
Listing 14.
HQL query in the search method of calling 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 detect Estates with the corresponding IDs, Hibernate needs to provide two queries to the database (Listing 15).
Listing 15.
SQL select queries 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 the second strategy, there is a "set singularity" relationship between the Right and Estate classes.
It translates something like this: "One Estate can refer to many Rights.
But each Right can only refer to one Estate."
In the light of our database model, there is no unique table that we can use to create a foreign key constraint, as between TB RIGHT and TB PERSON.
It is almost impossible for us to create a foreign key.
Fortunately, Hibernate provides us with a very powerful XML transformation element the <any> attribute, the use of which is demonstrated in Listing 16.
Listing 16.
XML transformation of various relationships <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> <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>
Blocked polymorphism Classes whose polymorphic support is blocked (<class...polymorphism= "explicit"...>) are excluded from targeting requests from any of the superclasses.
Let's take a closer look at this new part of the transformation.
Our virtual external code is based on two columns from the TB RIGHT table.
The first one (REF ESTATE TYPE) contains a discriminator string that will be used to convert the name of the corresponding class.
The second (REF ESTATE ID) is the column name from the primary key of another table.
Using the default settings, Hibernate will try to save the converted class names in the first column, which may be inefficient, but at the same time take up space in the table (especially if the class names change during code updates).
Fortunately, Hibernate provides the message of class names to string constants using the XML element <meta value>.
These constants serve the same purpose as the discriminators that we discuss in the second strategy.
Again, this attribute only includes Hibernate and the database, and this does not change the class hierarchy.
Integration of the database model
Also, standard SQL does not allow reference limiters simultaneously with numerous tables in a given column; it is possible to attach a procedure that checks for the presence of data in the final table that has received the discriminator property that it reads.
However, this method of implementing integration can be very difficult to apply and also reduce the participation of the entire database.
Polymorphism There is one thing to consider when using the built in Hibernate polymorphism: you can inadvertently return much more information; this is explained by the fact that all classes are converted by the polymorphism attribute set to implicit.
Listing 17 illustrates a way to return the entire database using an HQL query consisting of two words.
Listing 17.
HQL query public List all () {... List objects = session.find("from Object"); ... }
Pretty powerful, donot you think?
Of course, not many of you will need (or want, at least) to return the entire database with a single HQL query.
The purpose of this example (nonsense) is only to show the possibilities of implicit polymorphism.
You can use these features to prevent useless filling of the necessary resources when sending SQL queries to the database.
Conclusion In this article, we tried to give the simplest example for the implementation of the three strategies provided by Hibernate.
After all, every strategy has its advantages and disadvantages: Using our first strategy (one table per subclass) Hibernate reads numerous tables each time an object is defined and placed.
This operation can give good results if your indexes are well defined and the hierarchy is not too branched.
If, however, this is not the case, you may encounter problems in the overall execution of the task.
For the second strategy (one table per class hierarchy), you need to clearly define data integrity using validating constraints.
It may be difficult to use this strategy with a gradual increase in the number of columns.
On the other hand, you have the right not to use such limiters not at all, but to allow your application code to perform its own database integration.
Our third strategy (one table per specific class) has some limitations in the transformation; data model allocation cannot use referential integration; this means that you have not included the relational database engine in full force.
The "plus" is that this strategy can be freely combined with the other two.
No matter what strategy you choose, always remember that you do not need to delete your Java classes in the process; this means that there is absolutely no connection between your working objects and the stable foundation.
This is the degree of flexibility that makes Hibernate so popular in Java object relational projects.
At the beginning of the Download Description Name Size Code sample j hibernate source.zip ---
Resources The original article "Hibernate simplifies inheritance mapping" The Hibernate website provides all the necessary information depending on the basis with an object of continuous power.
You can download the Hibernate files that you will need to run the application from this site.
The HSQLDB database is an open source, lightweight database written exclusively in the Java language.
You can download HSQLDB from this site and use it as a database for the application.
See the HQL link for full information on the 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 guide for converting classes to database tables using Hibernate.
"Object relation mapping without the container," Richard Hightower (developerWorks, April 2004): An introduction to the development of a query processing layer using Hibernate and the Spring framework.
"Developing Hibernate applications for use with WebSphere Application Server," Sunil Patil (IBM WebSphere Developer Technical Journal, September 2004) provides step by step instructions for using the connection of the WebSphere Application Server and management transactions when creating Hibernate applications.
"Hibernate your data," Davor Cengija (ONJava.com, January 2004) gives the basis of the Hibernate API and describes how to benefit from these conversion files.
Hibernate in Action, Christian Bauer and Gavin King (Independent Pub Group, 2004) - a theoretical and practical guide to object relational transformation.
Written by the Hibernate team.
Hibernate: A Developer's Notebook, James Elliot (O'Reilly, 2004) - another great guide to Hibernate.
You can find hundreds of articles about every aspect of Java programming in the developerWorks Java technology zone.
Visit the Developer Bookstore to view a general list of technical books, including hundreds of titles related to Java.
Related links: Object relation mapping without the container Using Hibernate to persist your Java objects to IBM DB2 Universal Database Developing Hibernate applications for use with WebSphere Application Server IBM developer kits for the Java platform (downloads)
Comments
Close [x]
developerWorks: Log in
Required fields are marked with an asterisk (*).
IBM ID:*
Need an IBM ID?
Forgot your IBM ID?
Password:*
Forgot your password?
Change your password
Remember me.
By clicking Submit, you accept the Terms of Use of developerWorks.
The profile is created when you log in to developerWorks for the first time.
The information in your profile (name, country / region, company name) is displayed for all users and will accompany any content published by you as long as you are a specialist
