Using ORM tools in simple JDBC programs

This article comes from the "excellent course" -- to elaborate on the architecture.

ORM (object relational mapping) is an excellent tool for database programming. With a little experience and the power of Java annotations, we can build complex database systems and take advantage of productivity relatively easily. Relational databases are the body of most business applications. Mismatches between relational and object-oriented models are always difficult to map. ORM tools help us in a way that we can map objects to databases, as if we were using objects in an object-oriented model instead of records in a relational model. This changes the entire paradigm of JDBC programming.

Where is it suitable for JDBC

When you write normal JDBC code in Java, you will agree that it's really clumsy and laborious. Almost every time we make a CRUD request to the database, we write the same code over and over again. Now imagine what the world would be like if we could write:

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

 

POJO with no regular boilerplate code remains, and when we interact with a database in JDBC, we inevitably need to write it in some way. What's your opinion? Probably? Well, yes. Magic wands are ORM (object relational mapping) tools in Java. There are many ORM tools available on the market. Hibernate is one of them, and it's very efficient and reliable. In this article, we refer to the sample code as an example.

 

JDBC mode

JDBC requires a lot of code to manage connections and maintain rules to ensure that our application does not leak any resources. Look at the relatively large JDBC code below for a list of employee records.

 1 public List<Employee> getEmployees() {
 2         List<Employee> list = new ArrayList<>();
 3         Connection con = null;
 4         PreparedStatement pstmt = null;
 5         try {
 6             Class.forName("com.mysql.jdbc.Driver");
 7             con = DriverManager.getConnection("jdbc:mysql://localhost/minilibrary", "user1", "secret");
 8             pstmt = con.prepareStatement("SELECT * FROM emp ORDER BY empId");
 9             ResultSet rs = pstmt.executeQuery();
10             while (rs.next()) {
11                 Employee emp = new Employee();
12                 emp.setEmpId(rs.getInt(1));
13                 emp.setName(rs.getString(2));
14                 emp.setPhone(rs.getString(3));
15                 emp.setEmail(rs.getString(4));
16                 emp.setSalary(rs.getFloat(5));
17                 emp.setDesignation(rs.getString(6));
18                 list.add(emp);
19             }
20         } catch (SQLException | ClassNotFoundException ex) {
21             Logger.getLogger(EmployeeBean.class.getName()).log(Level.SEVERE, "Could not acquire record", ex);
22             throw new EmployeeException("Failed to retrieve employee from the database");
23         } finally {
24             try {
25                 if (pstmt != null) {
26                     pstmt.close();
27                 }
28                 if (con != null) {
29                     con.close();
30                 }
31             } catch (SQLException ex) {
32                 Logger.getLogger(EmployeeBean.class.getName()).log(Level.SEVERE, null, ex);
33             }
34         }
35         return list;
36     }

 

Although there are various techniques to reduce it to a fairly appropriate size, especially for opening the template part of the connection and recording problems, the main logic for extracting object instances from the ResultSet is still the same. This is even worse when the object contains references to other objects or collections of objects.

Input ORM

Hibernate alleviates many troubles of JDBC programming, and solves this problem in a more reasonable way, or we should say the object-oriented way. We can create a POJO from the selected table columns and save it in the database. Hibernate directly supports inheritance between classes and other object-oriented relationships. We can use these relational mechanisms to create one-to-one, one to many, many to many mappings at the relational database level. With the help of Java annotation @ Entity, it's easy to create entities. @Id means empId is the primary key of the database.

1 @Entity
2 public class Employee {
3     @Id
4     private int empId;
5     private String empName;
6 ...
7 }

 

The key of hibenate is configuration settings, which can be completed in an XML file commonly known as hibernate.cfg.xml. You can also set this configuration setting through Java code, as shown below.

 1 public class HibernateUtil {
 2 
 3      private static final  SessionFactory sessionFactory;
 4      private static final  ServiceRegistry serviceRegistry;
 5      static {
 6           try {
 7                Configuration config = getConfiguration();
 8                serviceRegistry = new ServiceRegistryBuilder().applySettings(
 9                          config.getProperties()).buildServiceRegistry();
10                config.setSessionFactoryObserver(new SessionFactoryObserver() {
11                     private static final long  serialVersionUID = 1L;
12  
13  
14  
15                     @Override
16                     public void sessionFactoryCreated(SessionFactory factory) {
17                     }
18  
19  
20  
21                     @Override
22                     public void sessionFactoryClosed(SessionFactory factory) {
23                          ServiceRegistryBuilder.destroy(serviceRegistry);
24                     }
25                });
26                sessionFactory = config.buildSessionFactory(serviceRegistry);
27           } catch (Throwable ex) {
28                System.err.println("Initial SessionFactory creation failed." + ex);
29                throw new ExceptionInInitializerError(ex);
30           }
31      }
32      public static  Session openSession() {
33           return sessionFactory.openSession();
34      }
35  
36  
37  
38      private static  Configuration getConfiguration() {
39           Configuration cfg = new Configuration();
40           cfg.addAnnotatedClass(Employee.class );
41           cfg.setProperty("hibernate.connection.driver_class","com.mysql.jdbc.Driver");
42           cfg.setProperty("hibernate.connection.url","jdbc:mysql://localhost/hr");
43           cfg.setProperty("hibernate.connection.username", "user1");
44           cfg.setProperty("hibernate.connection.password", "secret");
45           cfg.setProperty("hibernate.show_sql", "true");
46           cfg.setProperty("hibernate.dialect","org.hibernate.dialect.MySQLSQLDialect");
47           cfg.setProperty("hibernate.hbm2ddl.auto", "update");
48           cfg.setProperty("hibernate.cache.provider_class","org.hibernate.cache.NoCacheProvider");
49           cfg.setProperty("hibernate.current_session_context_class", "thread");
50           return cfg;
51      }
52 }

 

After setting the configuration properties, we can start. Now let's rewrite the JDBC version of the getEmployees function to get the list of employees.

1 public List<Employee> getEmployees(){        
2         Session s=HibernateUtil.openSession();
3         s.beginTransaction();
4         List<Employee> list=s.createQuery("FROM Employee").list();
5         s.getTransaction().commit();
6         s.close();                
7         return list;
8     }

 

It is not so simple and clear, and explains why any JDBC programmer uses Hibernate or any other ORM tool in database programming.

 

If ORM is the solution, is JDBC a problem?

No, no, JDBC is fine. In fact, in some cases (such as common CRUD operations), some type of object relational mapping is appropriate, while the traditional method of direct access through the JDBC connection API has the upper hand. ORM provides a layer of convenience for programmers. Is there a performance cost to this convenience. Well, there's a lot of anecdotal evidence of this disadvantage (although I haven't tested it yet), but I believe that the disadvantages of using ORM tools far outweigh the disadvantages. There is no war between them. One can make up for the other. From a higher perspective, we can say that the JDBC API can run independently in database programming, while the ORM tool cannot. Even if we obviously don't use the JDBC API in our code, ORM will always use the following JDBC API. So it's a ridiculous question to ask, in some way, which one should we choose? ORM sits between your application and JDBC, providing the missing link between the programming object-oriented model and the relational database model. In fact, this so-called ORM interacts with JDBC to finally talk to the database. The concept may be further illustrated in the figure below.

 

Figure 1: the role of hibernation in Java applications

 

conclusion

Hibernate can be called directly from a Java application or accessed through another framework. Whether it's a Swing application, a Servlet, a JSP page, or any other Java application that has access to the database, we usually use it to create a data access layer for the application or replace the existing data access layer. Other ORM tools, such as MyBatis, perform similar functions through different API s and access mechanisms. In general, ORM, especially hibernate, is more powerful and in-depth than this advanced overview. Perhaps this article provides first-hand insights and intrigues you to explore the depth of rabbit holes.

 

Thank you for reading! Finally, I present a complete set of java architecture mind map sorted out recently to share with you for reference.

Keywords: Java JDBC Hibernate Database

Added by bufke on Thu, 16 Jan 2020 11:22:28 +0200