December 22, 2014
Hot Topics:

Using the ORM Tool in a Simple JDBC Program

  • May 2, 2014
  • By Manoj Debnath
  • Send Email »
  • More Articles »

ORM (Object Relational Mapping) is an amazing tool for database programming. With a little experience and the power of Java annotation we can build complex database systems with relative ease and leverage productivity. The relational database is the mainstay of most commercial applications. The mismatch between the relational model and object oriented model is always difficult to map. The ORM tool helps us in a way where objects can be mapped into the database as if we are no longer working with records of the relational model but objects in an object oriented model. This changes the whole paradigm of JDBC programming.

Where Does it Fit in JDBC

While working with plain JDBC code in Java, you'll agree that it really feels clumsy and strenuous, writing the same code over and over again almost every time we make a CRUD request to the database. Now, imagine how the world would be if we could write something like:

MyPojo hmm=new MyPojo();
MagicWand wave=MagicWand.getInstance();
wave.save(hmm);

And persist a POJO without the regular boiler plate code that we inevitably need to write some way or the other while interacting with the database in JDBC. What do you think? Possible? Well, it is. The magic wand is the ORM (Object Relational Mapping) tool in Java. There are quite a few ORM tools available in the market. Hibernate is one of them and is quite an efficient and reliable one. We shall use it as an instance in this article to cite example code down the line.

Way of JDBC

JDBC requires a considerable body of code to manage the connection and maintain various rules to ensure that no resource is leaked by our application. Look at the following relatively huge JDBC code to fetch a list of employee records.

public List<Employee> getEmployees() {
        List<Employee> list = new ArrayList<>();
        Connection con = null;
        PreparedStatement pstmt = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            con = DriverManager.getConnection("jdbc:mysql://localhost/minilibrary", "user1", "secret");
            pstmt = con.prepareStatement("SELECT * FROM emp ORDER BY empId");
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                Employee emp = new Employee();
                emp.setEmpId(rs.getInt(1));
                emp.setName(rs.getString(2));
                emp.setPhone(rs.getString(3));
                emp.setEmail(rs.getString(4));
                emp.setSalary(rs.getFloat(5));
                emp.setDesignation(rs.getString(6));
                list.add(emp);
            }
        } catch (SQLException | ClassNotFoundException ex) {
            Logger.getLogger(EmployeeBean.class.getName()).log(Level.SEVERE, "Could not acquire record", ex);
            throw new EmployeeException("Failed to retrieve employee from the database");
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (con != null) {
                    con.close();
                }
            } catch (SQLException ex) {
                Logger.getLogger(EmployeeBean.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return list;
    }

Though there are various techniques to trim this down to a pretty decent size, especially the boilerplate part for opening connections and logging problems, but the primary logic to pull an object instance from the ResultSet remains the same. The situation turns even worse when the object includes references to other objects or a collection of objects.

Enter the ORM

Hibernate alleviates a lot of the pain of JDBC programming and addresses the issue in a more rational way or should we say object oriented way. We can create a POJO from a selection of table columns and persist it in the database. Hibernate directly supports inheritance and other object oriented relationships between classes. We can use these relationship mechanisms to establish one-to-one, one-to-many, many-to-many mapping in the relational database level. Creation of an entity is simple with the help of Java annotation @Entity. @Id refers empId is the primary key of the database.

@Entity
public class Employee {
    @Id
    private int empId;
    private String empName;
...
}

The crux of the hibenate is in the configuration settings, which can be accomplished in an XML file, commonly referred as hibernate.cfg.xml. This configuration setting can also be set through Java code as shown below.

public class HibernateUtil {

     private static final  SessionFactory sessionFactory;
     private static final  ServiceRegistry serviceRegistry;
     static {
          try {
               Configuration config = getConfiguration();
               serviceRegistry = new ServiceRegistryBuilder().applySettings(
                         config.getProperties()).buildServiceRegistry();
               config.setSessionFactoryObserver(new SessionFactoryObserver() {
                    private static final long  serialVersionUID = 1L;



                    @Override
                    public void sessionFactoryCreated(SessionFactory factory) {
                    }



                    @Override
                    public void sessionFactoryClosed(SessionFactory factory) {
                         ServiceRegistryBuilder.destroy(serviceRegistry);
                    }
               });
               sessionFactory = config.buildSessionFactory(serviceRegistry);
          } catch (Throwable ex) {
               System.err.println("Initial SessionFactory creation failed." + ex);
               throw new ExceptionInInitializerError(ex);
          }
     }
     public static  Session openSession() {
          return sessionFactory.openSession();
     }



     private static  Configuration getConfiguration() {
          Configuration cfg = new Configuration();
          cfg.addAnnotatedClass(Employee.class );
          cfg.setProperty("hibernate.connection.driver_class","com.mysql.jdbc.Driver");
          cfg.setProperty("hibernate.connection.url","jdbc:mysql://localhost/hr");
          cfg.setProperty("hibernate.connection.username", "user1");
          cfg.setProperty("hibernate.connection.password", "secret");
          cfg.setProperty("hibernate.show_sql", "true");
          cfg.setProperty("hibernate.dialect","org.hibernate.dialect.MySQLSQLDialect");
          cfg.setProperty("hibernate.hbm2ddl.auto", "update");
          cfg.setProperty("hibernate.cache.provider_class","org.hibernate.cache.NoCacheProvider");
          cfg.setProperty("hibernate.current_session_context_class", "thread");
          return cfg;
     }
}

Once the configuration properties are set, we are good to go. Now let us rewrite the JDBC version of the getEmployees function to fetch the list of employees.

public List<Employee> getEmployees(){        
        Session s=HibernateUtil.openSession();
        s.beginTransaction();
        List<Employee> list=s.createQuery("FROM Employee").list();
        s.getTransaction().commit();
        s.close();                
        return list;
    }

Isn't that simple, clear and justifies why any JDBC programmer embraces Hibernate or any other ORM tool in database programming.

If ORM is the Solution, is JDBC a Problem?

No, no, JDBC is perfectly alright. In fact there are situations like common CRUD operations where some sort of object relational mapping is appropriate, and where the traditional approach of direct access via the JDBC connectivity API reigns supreme. ORM provides a layer of convenience for the programmer. Does this convenience come with a price of performance. Well, there are anecdotal evidences of this downside (though I haven't tested), yet I believe the upside of using the ORM tool far outweighs its disadvantage. There is no war between them; rather one complements the shortcomings of the other. From a high level point of view we can say – the JDBC API can standalone in database programming but a ORM tool cannot. Even if we visibly do not use JDBC API in our code, ORM always takes the help of the JDBC API beneath. So in a way it would be an absurd question to ask which one should we choose? ORM sits in between your application and JDBC providing the missing link between the object oriented model and relational database model of programming. In fact this so called ORM interacts with the JDBC to talk to the database ultimately. Perhaps the figure below would clarify the concept further.

Role of Hibernate in a Java application
Fig 1: Role of hibernate in a Java application

Conclusion

Hibernate can be called from a Java application directly or we can access it through another framework. Be it a Swing application, a Servlet, a JSP page or any other Java application that has access to a database, we typically use it to either create as data access layer for an application or replace an existing data access layer. Other ORM tools such as MyBatis perform similar functions with a variation of API and access mechanism. ORM in general and Hibernate in particular is more powerful and deeper than this high level overview. Perhaps this article gives a first hand insight and intrigues you to explore how deep the rabbit hole goes.


Tags: Java, Object relational mapping, database, JDBC




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel