Headline

Object-Relational mapping for Java with Hibernate

Motivation

Object-Relational mapping or persistence on the Java platform is exercised using Technology:Hibernate. The primary data model for companies is a straightforward object model for POJOs. A mapping is defined to associate a relational schema with the classes. The mapping is specified in an Language:XML language and organized in a per-class manner. For each class, properties and relationships are specified by the mapping. It is insightful to compare the object model and the mapping-implied relational schema. It is also insightful to compare the latter schema with one that was natively designed from a relational database point of view; see Contribution:mySqlMany. In particular, the object model and the implied relational schema are essentially "optimized" for downwards traversal of the company structure whereas a native relational schema would rather provide foreign keys for upwards navigation (such as navigating from an employee to its department or company).

Illustration

Consider the following sketch of the class for departments:

public class Department {
  private Long id;
  private String name;
  private Set<Employee> employees;
  private Set<Department> subdepts;

  public Long getId() { ... }
  private void setId(Long id) { ... }
  public String getName() { ... }
  public void setName(String name) { ... }
  public Set<Employee> getEmployees() { ... }
  private void setEmployees(Set<Employee> employees) { ... }
  public Set<Department> getSubdepts() { ... }
  private void setSubdepts(Set<Department> subdepts) { ... }
}

Each persistent class must provide a property (i.e., a getter and a setter) for an id that can serve as primary key in the database. Properties of collection types (in fact, set types) proxy for one-to-many relationships. Other than that, a persistent class is not much different from a regular POJO-like class. (There are some private setters that would be missing from a native object model. These setters are needed for object population.)

Consider the mapping file of class Department to table DEPARTMENT:

<hibernate-mapping>
 <class name="org.softlang.company.Department" table="DEPARTMENT">
  <id name="id" column="ID">
    <generator class="native" />
  </id>
  <property name="name" />
  <set name="employees" cascade="all">
   <key column="DEPT ID" />
   <one-to-many class="org.softlang.company.Employee" />
  </set>
  <set name="subdepts" cascade="all">
   <key column="DEPT ID" />
   <one-to-many class="org.softlang.company.Department" />
  </set>
 </class>
</hibernate-mapping>

All properties of the class are associated with the table. That is, the id property is directly mapped to a primary key column ID of the DEPARTMENT table. Also, the name property is mapped to a column of just that name---applying default mapping rules between SQL types and Java types. Further, the employees property is non-trivially associated with a foreign key DEPT ID of the EMPLOYEE table---which is only indirectly identified through the mentioning of the Employee class; likewise for sub-departments.

Persistent objects are brought back to life as follows:

public Company loadCompany(String name) {
  this.session = getSessionFactory().getCurrentSession();
  this.session.beginTransaction();
  List<?> result = this.session.createQuery(
    "from Company where name = '" + name + "'").list();
  for (Object o : result)
    return (Company)o;
  return null;
}

That is, an Language:HQL query is executed to retrieve a company that is identified by name; the Hibernate framework takes care of populating the company object and all its sub-objects. If the requested company cannot be found, then null is returned.

Finally, consider the Hibernate configuration:

<hibernate-configuration>
 <session-factory>
  
  <property name="connection.driver class">org.hsqldb....
  <property name="connection.url">...
  <property name="connection.username">...
  <property name="connection.password">...
   
  <property name="hbm2ddl.auto">update</property>			  			  
  
  <mapping resource="org/softlang/company/Company.hbm.xml" />
  <mapping resource="org/softlang/company/Department.hbm.xml" />
  <mapping resource="org/softlang/company/Employee.hbm.xml" />
  ...
 </session-factory>
</hibernate-configuration>

This configuration helps the runtime to connect to the right database, to find all mapping files of interest, and to define some essential settings. For instance, Hibernate is informed here that the database catalog is to be updated automatically (see hbm2ddl.auto ... update) upon starting a Hibernate session. In particular, if the mapping-implied tables are not yet declared in the database, then they will be created automatically.

Architecture

Package org.softlang.company hosts the java object model for Feature:Hierarchical company and the O/R-mapping files. Package org.softlang.features provides functionality for Feature:Total and Feature:Cut as well as boilerplate code for Feature:Persistence. The folder scripts contains SQL-scripts to create tables (extracted from the hibernate log; there is no need to execute these statements), and to populate the tables (needed in the workflow described below). The Hibernate configuration file is located in the root dir. The HSQLDB database files are located in the data dir.

Usage

Please follow these steps carefully.

Start from a clean setup

Upon checking out the implementation, you are clean.

The "make clean" target in the root dir should bring you back to a clean setup.

However, make sure the HSQL database server is shutdown as you go clean.

Build the project

This is an Eclipse project.

Everything is included.

The project should built fine within Eclipse without additional efforts.

Start the HSQL database server

  • Go to the data dir of the distribution.
  • Run the following command in the command line:
    • > java -classpath ../lib/hsqldb.jar org.hsqldb.Server
    • You can also send it to the background if you like.
    • You can also go to the root dir and run "make start-db" instead.

Start the database monitor

  • Go to the root dir of the distribution.
  • Run the following command in the command line:
    • > java -classpath lib/hsqldb.jar org.hsqldb.util.DatabaseManagerSwing
    • You can also send it to the background if you like.
    • You can also go to the root dir and run "make start-gui" instead.
  • When the GUI pops up, make sure to select "HSQL Database Engine Server".

Create tables

The tables are automatically created by trying to query them.

There is JUnit test Load in package org.softlang.tests which just does that.

Do refresh in the database monitor to see all tables in the left panel.

Populate tables

Suitable INSERT statements for population are to be found in scripts/PopulateTables.sql

Open the file and copy and paste its content over to the database monitor, and execute the statements.

You may want to double-check that the tables were populated.

To this end, enter a SQL statement such as "select * from EMPLOYEE;".

Proper testing

Several test cases are collected in package org.softlang.tests:

  • Run the JUnit test Check for checking for the ranking constraint. This test does not modify the state of the database. This test succeeds repeatedly (since even the cut transformation does not end up violating the constraint).
  • Run the JUnit test Query for computing the salary total. This test does not modify the state of the database. This test succeeds repeatedly for as long as the computed total equals the baseline that is hard-coded in that test.
  • Run the JUnit test TransformNoSave for cutting all salaries. This test does not modify the state of the database. This test succeeds repeatedly (since the totals before and after cut are compared without using any hard-coded baseline for total).
  • Run the JUnit test TransformAndSave for cutting all salaries. This test modifies the state of the database and thus makes fail test Query. This test succeeds repeatedly (since the totals before and after cut are compared without using any hard-coded baseline for total).

Finish off

Go to the database monitor and enter and execute "shutdown;".

Quit the database monitor.

You may also want to run "make clean" in the root dir to be clean for next time.

Metadata


There are no revisions for this page.

User contributions

    This user never has never made submissions.

    User edits

    Syntax for editing wiki

    For you are available next options:

    will make text bold.

    will make text italic.

    will make text underlined.

    will make text striked.

    will allow you to paste code headline into the page.

    will allow you to link into the page.

    will allow you to paste code with syntax highlight into the page. You will need to define used programming language.

    will allow you to paste image into the page.

    is list with bullets.

    is list with numbers.

    will allow your to insert slideshare presentation into the page. You need to copy link to presentation and insert it as parameter in this tag.

    will allow your to insert youtube video into the page. You need to copy link to youtube page with video and insert it as parameter in this tag.

    will allow your to insert code snippets from @worker.

    Syntax for editing wiki

    For you are available next options:

    will make text bold.

    will make text italic.

    will make text underlined.

    will make text striked.

    will allow you to paste code headline into the page.

    will allow you to link into the page.

    will allow you to paste code with syntax highlight into the page. You will need to define used programming language.

    will allow you to paste image into the page.

    is list with bullets.

    is list with numbers.

    will allow your to insert slideshare presentation into the page. You need to copy link to presentation and insert it as parameter in this tag.

    will allow your to insert youtube video into the page. You need to copy link to youtube page with video and insert it as parameter in this tag.

    will allow your to insert code snippets from @worker.