Hibernate has many advantages compared to other similar object relationship mappings (JDO, entity bean, internal development, etc.), Hibernate has many advantages: it is free, open source, has matured to a good degree, and has been widely used, and there is also a very Active community forum.
To integrate Hibernate into an existing Java project, you need to perform the following steps:
Download the latest release of the Hibernate framework from Hibernate's Web Sites (see the link in the reference) section.) Copy the necessary Hibernate library (JAR file) to the application's classpath. Create an XML configuration file and use it to map the Java object to the database table. (We will describe this process herein.) Copy the XML configuration file to the application's classpath.
You will notice that you don't have to modify any Java objects, you can support the framework. For example, suppose you have changed some modifications to the database table used by the Java application - such as the column name. After modifying the table, you are just updating the corresponding XML profile. You don't need to recompile any Java code.
Hibernate Query Language (HQL) Hibernate provides a query language called Hibernate Query Language (HQL), which is very similar to SQL. If you like to use old-fashioned SQL queries, Hibernate also provides you with opportunities to use them. But the example we use is only HQL.
HQL is quite simple. You will find that all keywords are similar to keywords in SQL you are familiar with, such as SELECT, FROM, and WHERE. The difference between HQL and SQL is that you do not have to write queries directly for data models (ie, tables, etc., etc.), but should write queries for Java objects, with the property and relationship of Java objects.
Listing 1 demonstrates an essential example. This HQL code retrieves all Individual for "John.".
Listing 1. Basic HQL query
Select * from eg.hibernate.mapping.dataObject.individual where firstname = "john"
If you want to know more about HQL syntax, you can see the reference material for HQL on the WEB site of Hibernate (see Resources for link).
The core of the XML configuration file is in the XML configuration file. These files must exist in the ClassPath of the application. We put them in the Config directory of the sample code package (you can download it from the reference).
The first file we have to study is hibernate.cfg.xml. It contains information related to the data source (database URL, pattern name, user name, password, etc.), and reference to other configuration files containing mapping information.
The rest of the XML file allows you to map the Java class to the database table. I will introduce these files later, but it is important to know their file name to comply with the classname.hbm.xml mode.
Our support examples are herein, we have to study a basic example, how Hibernate works, how to use three different strategies, using Hibernate to make an object relationship mapping. Our example is an application used by an insurance company, and the company must maintain the legal record of all property rights insured. We provide a complete source code with this (see Resources); this code provides basic functions, you can build full-featured applications, such as web or swing applications. Our example uses a classic use case of such applications. Users provide search parameters to find various types of customers (individuals, companies, government agencies, etc.), then display all customers who match the specified parameters - even if the types of these customers are different. Users can access a more detailed view of a particular customer in the same list.
In our app, property rights are represented by the Right class. Right can be Lease or ProPerty. Right is owned by customers. In order to express our customers, we have to use universal class Person. Person can be INDIVIDUAL or Corporation. Of course, insurance companies must know which ESTATE is assigned to these Rights. You should agree that the meaning of the term ESTATE is very broad. So, we have to provide our developers to our developers with Land and Building classes.
From this abstraction, we can develop the class model shown in Figure 1:
Figure 1. Complete class model
Our database model is designed to introduce three different strategies discussed herein. For the Right hierarchy, we want to use a table (TB_Right) and map the discriminator column to the correct class. For the Person structure, we want to use a table called a super-table (TB_PERSON), which share the same ID as the other two tables (TB_Corporation, and TB_INDIVIDUAL). The third hierarchy (ESTATE) uses two different tables (TB_BUILDING and TB_LAND), which are connected by a foreign key defined by two columns (REF_ESTATE_ID and REF_ESTATE_TYPE).
Figure 2 shows this data model:
Figure 2. Complete data model
Setting the database Hibernate supports a wide variety of RDBMs, where any of our examples can be used. However, the sample code and text of this article have been adjusted for HSQLDB (see Refiguring Links), which is a full-featured relational database system that is fully written in Java language. In the SQL directory of the sample code package, you can find a file called DataModel.sql. This SQL script can create the data model used in our example.
Setting the Java project Although you can also build and implement sample code with the command line, you may want to set up items in the IDE to better integrate. In the sample code package, you can find the following directory:
Config, contain all XML configuration files (mapping, log4j, etc.) for the sample. Data, contains the configuration files used by HSQLDB. You can also find a batch file called StartHsqldb.bat, you can use it to start the database. SRC, contain all source code of the example.
Make sure to copy the required Java library and XML configuration files to the application's classpath. It only needs Hibernate and HSQLDB libraries, which can be compiled and run correctly. You can download these packages from the reference section. Policy 1: One table of each subclass (Persons) In our first policy, we have to see how to map our Person hierarchy. You will notice that the data model is very close to our class model. So, we have to adopt a different table for each class in the hierarchy, but all of these tables must share the same primary key (we will detail soon). Hibernate uses this primary key when inserting a new record into the database. When accessing the database, it will use the same primary key to perform JOIN operations.
Now we need to map the object hierarchy to the table model. We have three tables (TB_Person, TB_INDIVIDUAL, and TB_CORPORATION). We have mentioned before, they all have a column called the ID and use the column as the primary key. There are not necessarily such a shared column name between the table, but this is a good practice - what to do, the generated SQL query is easier to read.
In the XML mapping file shown in Listing 2, you will notice that in the Person's mapping definition, two specific
Listing 2. Person.hbm.xml
XML Version = "1.0" encoding = "UTF-8"?>
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
id>
set>
joined-subclass>
joined-subclass>
clas>
hibernate-maping>
Save a new instance of Individual to form a Java code we use Hibernate, as shown in Listing 3:
Listing 3. Save 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 ();
...
}
Next, Hibernate generates two SQL INSERT requests, as shown in Listing 4. These two requests are one SAVE ().
Listing 4. SQL insertion query
INSERT INTO TB_PERSON (ID) VALUES (?)
INSERT INTO TB_INDIVIDUAL (first_name, last_name, id) Values (?,?,?
To access Individual in the database, just specify the class name in the HQL query, as shown in Listing 5.
Listing 5. Call 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 automatically performs SQL's Join, retrieves all necessary information from both tables, as shown in Listing 6:
Listing 6. Finding Individual SQL SELECT queries
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 =?)
Query Abstract Class When querying an abstract class, Hibernate automatically returns a collection that makes up by matching specific isomeric subclasses. For example, if we query each of the Person in the database, Hibernate returns a column of Individual and Corporation objects.
However, when not specified a specific class, Hibernate needs to perform SQL's Join because it doesn't know which table is to be queried. In the columns of the retrieved tables returned to the HQL query, an additional Dynamic column will also be returned. Hibernate initializes and fills the returned object using the CLAZZ column. We call this class as a decision factor, which is relative to the method we used in the second policy.
Listing 7 shows how to specify an ID attribute query abstract class Person, inventory 8 shows the Hibernate automatically generated SQL query, including a table connection:
Listing 7. Find () method call in the HQL query
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. Find any type of Person's SQL SELECT query
SELECT PERSON0_.ID AS ID0_,
Casewhen (persot 0__1_.id is not null, 1,
Casewhen (persot 0__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 OTER JOIN TB_INDIVIVIDUAL PERSON0__1_ on person0_.id = person0__1_.id
LEFT OTER JOIN TB_CORPORATION PERSON0__2_ on person0_.id = person0__2_.id
WHERE PERSON0_.ID =?
Strategy 2: Each class hierarchy is a table (Rights) For our Right hierarchy, we only use a table (TB_Right) to save the overall class hierarchy. You will notice that the TB_Right table has all the columns required to save each attribute of the Right class hierarchy. The saved instance value will be saved in the table, and each column that is not used is filled with a null value. (Because it is a "hole" everywhere, we often call it as a Swiss cheese.
In Figure 3, you will notice that the TB_RIGHT table contains an additional column discriminator. Hibernate is automatically initialized with this column and fills accordingly. This class is mapping the XML element
Concise skills in each large project, you will face a complex class hierarchy containing multi-level abstract classes. Fortunately, you don't have to specify discriminator-value of an abstract class, just specify this value for the specific class you want to use by Hibernate.
As the Person mapping file shown in Listing 2, in Listing 9, we map the abstract class (Right) and all its properties. To map two specific classes (Lease and Property), use the
From the class diagram of Figure 1, you will notice that Discriminator is not attributes with any Java classes. In fact, it doesn't even mapping. It is just a technical column shared between Hibernate and databases.
Listing 9. Right.hbm.xml
XML Version = "1.0" encoding = "UTF-8"?>
"- // Hibernate / Hibernate mapping DTD 2.0 // en"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
id>
discriminator>
Meta-type = "string" ID-TYPE = "java.lang.integer"> any> subclass> clas> hibernate-maping> In the mapping file of the List 9, you will notice the "multi-to-one" relationship between the Right and the Person hierarchy, which (substantially) is opposite to the Person hierarchy (one-to-many). Please also pay attention to the relationship between the Right and ESTATE hierarchies; later we will introduce this relationship herein. When using the first policy, Hibernate generates a very efficient SQL statement when accessing the database. When we query the specific class, as shown in Listing 10, you will automatically take the value on the Hibernate filter of Discriminator - this is a good thing, because this means that Hibernate reads only the column corresponding to the specified class. Listing 10. SQL query for specific classes SELECT Property0_.id AS ID, Property0_.date as date, Property0_.ref_person_id as ref_pers4_, proty0_.ref_estate_type as ref_esta5_, Property0_.ref_estate_id as ref_esta6_ From TB_Right Property0_ Where property0_.discriminator = 'PRO' When we query about abstract classes, things become more complicated. Because hibernate does not know which particular class you want to query, you must read each column (including the discriminator class), and then decide which class to initialize, and finally fill it. Next, the role acting as the discriminator is the same as the role acting as the CLAZZ column in the first policy. But this method is obviously a deadline because class name is directly derived from the value of discriminator. Listing 11. (Abstract) Right class SQL query SELECT RIGHT_.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_ policy is not compatible with the Hibernate mapped DTD definition, the first two strategies described in this article are mutually exclusive, which means they cannot be combined, mapping the same hierarchy. The integrity of the database model is about the second policy, there is a place that needs to be considered: in order to make it work, all non-shared columns must be set to Nullable. Because developers usually rely on database constraints, the generated table may be very difficult. (After all, it doesn't make much sense to set the LEASE for duration to null!) One of the solutions is to use database-level detection constraints. You can define a set of rules to implement based on the value of Discriminator, as shown in Listing 12. Of course, the database engine must support these features. Moreover, these constraints must be expressed in a valid expression of all specific classes, which will be difficult to maintain when the hierarchy is developed. 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: Each specific class (ESTATES) Our third, and the last policy may be the most imagination of three strategies: one table of each specific class, abstract super-class Estate has no table. We rely on Hibernate to provide support for Polymorphism. In the XML mapping file shown in Listing 3, you will notice that only two specific classes are mapped (building and land): Listing 13. Estate.hbm.xml XML Version = "1.0" encoding = "UTF-8"?>
"- // Hibernate / Hibernate mapping DTD 2.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> id> id> clas> hibernate-maping> The shared ID value in the table is in that the same ID value is not required between the two tables mapped in the same class hierarchy. If you make a mapping, Hibernate returns multiple different objects for the same ID. This may make Hibernate to mix - you will also mix. When you view the mapping file in Listing 13, your first reaction may be said: "Oh! This map is nothing different from me! There is not an important thing here!" And you want to be right. . In fact, the third policy requires only one condition: you need to set the PolyMorphism property to IMPLICIT. It still exists in the class hierarchy even if the ESTATE class is found in the mapping file. Moreover, because the two mappings and LANDs are inherited from ESTATE, we can use this abstract superclass in the HQL query, as shown in Listing 14. Hibernate will use the Introspection to find classes that extend this abstract class in order to execute the corresponding SQL query for each subclass. Listing 14. Find () method call in the HQL query 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}); ... } In order to find Estate that matches the specified ID, Hibernate must submit two queries in Listing 15 to the database. Listing 15. SQL query 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 addressFrom tb_building building0_where (building0_.id =?) As we see in the second policy, there is a multi-to-one relationship between Right and Estate classes. In a general expression, the relationship between these two tables can be present: "An Estate can point to many Right. But each Right can only point to an ESTATE." But from our data model, we have no unique Tables can be used to create our foreign key constraints, just like TB_RIGHT and TB_PERSON. This makes us almost impossible to create foreign keys. Fortunately, Hibernate provides us with a very powerful XML mapping element - Listing 16. XML mapping of Any relationship Meta-type = "string" ID-TYPE = "java.lang.integer"> any> Prohibiting polymorphisms are prohibited for polymorphism ( We will further check our new mapping. Our virtual foreign key is based on two columns of the TB_Right table. The first column (REF_ESTATE_TYPE) contains the discriminator string that maps the corresponding class name with this string. The second (Ref_ESTATE_ID) is the column name of the primary key of another table. When using the default setting, Hibernate saves the class name in the first column, which may be very consumed, no efficiency (especially when code reconstruction modification class name). Thank you, Hibernate also provides a method of maping the class name to a string constraint with The integrity of the database model Although the standard SQL does not allow reference constraints for multiple tables, it is still possible to add triggers, depending on the read discriminator value, the trigger detects whether there is data in the directory. However, such integrity implementation may be very difficult to maintain, and it is possible to reduce the overall performance of data. Polymorphism - use the limit! When using the Hibernate built-in polymorphism, you need to remember one thing: If you are not careful, put all the classes with the PolyMorphism property to Implicit, then the information you have retrieved may be much more than you want. Listing 17 shows a method of retrieving the entire database using two HQL queries to retrieve the entire database. Listing 17. HQL query Public List all () { ... List Objects = session.find ("from object"); ... } The function of the query is very powerful, what do you think? Of course, there are not many people in us need to retrieve the entire database using only one HQL query. The purpose of this (without practical significance) is to show implicit polymorphism. You can use this ability to avoid sending useless, resource-consuming SQL queries to the database. Conclusion In this article, we try to provide you with a fairly simple implementation example, demonstrating the three mappings provided by Hibernate. Looking back, each strategy has its own advantages and deficiencies: For the first policy (one table of each subclass), Hibernate is read each time and fill the object, multiple tables are read. If your index is defined very well, and the hierarchy is not too deep, this operation can produce good results. However, if this is not this, you may encounter a variety of performance issues. For the second policy (one table for each class hierarchy), you must define your own integrity with the detection constraint. But as the number of columns increases, this strategy may become difficult to maintain. On the other hand, you may choose whether you don't have to restrain it, but rely on the application's code to manage your data integrity. The third policy (one table for each specific class) has some mapping limitations, and the underlying data model cannot use reference integrity, which means you can't play all the potential of the relational database engine. However, from a good aspect, the strategy is often easy to be combined with the other two strategies. No matter which strategy you choose, remember that in the whole process, there is no need to modify the Java class, which means that there is no connection between business objects and persistent frameworks. It is this high level of flexibility to make Hibernate in this popular in the Object Relations Java project. Reference You can see this article in our website on our world. Click on the source code example used in this article on the top or bottom of this article. Hibernate Site provides all information about this powerful object persistence framework. You can download the Hibernate file you need to run the sample application from this site. The HSQLDB database is an open source lightweight database that is fully written in Java language. You can download HSQLDB from this site and use it as a database of sample applications. See Hibl Reference written by Hibernate to get the full document of the Hibernate query language. "Using Hibernate to Persist your Java Objects to IBM DB2 Universal Database", the author is Javid Jamae and Kulvir Singh Bhogal (United States, June 2003), which provides good guidance that maps classes to the database table with Hibernate. "Object Relationship Map of Containers", the author is Richard Hightower, (DeveloperWorks, April 2004), which introduces the Hibernate and Spring Framework Development Transaction Persistence. "Developing Hibernate Application SERVER", author SUNIL PATIL (IBM WebSphere Developer Technical Journal, September 2004), providing detailed guidance from WebSphere Application Server connection and transaction management when creating a Hibernate application. "Hibernate Your Data", the author is Davor Cengija (ONJAVA.com, Jan 2004), which provides all the basic knowledge of the Hibernate API describing how to use the Hibernate API mapping file. Hibernate In Action, the author is Christian Bauer and Gavin King (Independent Pub Group, 2004), which is the theoretical and practical guide for object relationship mapping. Written by the Hibernate team. Hibernate: A Developer's Notebook, the author is James Elliot (O'Reilly, 2004), which is another hibernate's wonderful guide. In the developerWorks Java technology area, hundreds of technical articles about Java are available. Please visit developer bookstore to get a full list of technical books, including hundreds of Java-related topics. download Name Size Download Method J-Hibernate-source.zip FTP