JDBC - InshortsView

|
Divnesh BLOG
InfyBank is India's largest private sector bank.  It offers wide range of services including loans, lockers, accounts, deposits, etc. to its customers.  You are asked to build a banking application for InfyBank to automate their business process where few of the requirements are as mentioned below.
1. Retrieve the customer details based on various conditions like retrieval by name, by account number, by customer id, etc.
2. Store the new customer details into database.
InfyBank maintains its customer details in Oracle database.  The table structure and few sample customer records are shown below.
2
Can you solve these requirement using Java I/O?
No, your Java program cannot interact with a database using Java I/O streams.  You need to use a Java technology which enables the Java program to access database. Java Database Connectivity is one such Java technology.
JDBC API  is a specification which tells the Java application how to communicate with any relational database like MySQL, Oracle, DB2, etc. JDBC comes under Java SE and its functionalities are available under java.sql and javax.sql packages.
Using the classes and interfaces available in java.sql and javax.sql packages, you can perform the database CRUD operations easily. CRUD stands for..
3
Let us discuss how to perform the CRUD operations using JDBC API to solve the InfyBank requirements
Retrieving Data From Database
Below is the sample JDBC code to retrieve the customer details from CUSTOMER table based on the given customer name.  Observe the highlighted part of the code.
public class CustomerDAO {
  public void getCustomerDetails()throws Exception{
        tring sql="select * from customer where customerName='George'";           // SQL statement to be compiled and reused
        Class.forName("oracle.jdbc.driver.OracleDriver");                         //1.loads the driver
        try (Connection connection=DriverManager.getConnection("jdbc:oracle:thin:username/password@10.120.79.57:1521:georli01");  
                PreparedStatement pStatement=connection.prepareStatement(sql)     // 2 & 3. creates Connection and PreparedStatemet instance
             ){          
                 ResultSet resultSet=pStatement.executeQuery();                   //4. executes the statement 
                 while(resultSet.next()){                                         //5. processes the result
                    Integer id=resultSet.getInt(1);
                    String customerName=resultSet.getString("customerName");
                    String city=resultSet.getString("city");
                    Long phoneNumber=resultset.getLong(4);
                    System.out.println("Customer Id : "+id);
                    System.out.println("Customer Name : "+customerName);
                    System.out.println("City : "+city);
                    System.out.println("Phone Number : "+phoneNumber);
                 }
            } catch (SQLException exception) {          
            throw exception;
            }  catch (Exception exception) {
            throw exception;
          }
     }
 }
Below are the steps we used in the code.
  1. Load the driver
  2. Create the connection
  3. Prepare the statement
  4. Execute the statement
  5. Process the result
  6. Close the connection (try-with-resources used)

What is a driver?

Driver is a software component which connects two dissimilar environments.  For example, if you want to connect a web camera with your desktop, you need a Webcam Driver. Similarly, a Java application and the database server are two completely heterogeneous environments. So we need a driver called as JDBC driver to connect them
4
The database vendors have to implement java.sql.Driver interface of JDBC API in order to build a driver class using which a Java application will be able to connect and communicate with their product.
JDBC drivers can be of following types:
  • Type 1 (JDBC-ODBC bridge driver)
  • Type 2 (JDBC native-API driver)
  • Type 3 (network-protocol or middleware driver)
  • Type 4 (database-protocol or pure Java driver)
Type 4 drivers are platform independent as it is written entirely using Java language. So, this driver is the most preferred one for enterprise application development. In this course, we will be using Type 4 driver of Oracle database.

Load the Driver

To access a relational database from a Java application, the JDBC driver class for that database first should be loaded into the application's classpath. 
As we are going to use Oracle database for practice, we need to use the driver class provided by Oracle vendor.  
Below mentioned code loads the type 4 driver class oracle.jdbc.driver.OracleDriver of Oracle database into application's classpath.
Class.forName("oracle.jdbc.driver.OracleDriver");
The forName() method of java.lang.Class is used in the code.
           Class.forName(driverClass);
If you want to connect with multiple databases like Oracle, MySQL, DB2, etc., you can invoke forName() multiple times from its respective driver classes. The loaded driver classes get registered with your application and is managed by java.sql.DriverManager class
5
Note: The OracleDriver.java file is given in the form of jar file (ojdbc7.jar) by Oracle vendor.  So, you need to configure that jar in your application's buildpath in order to load its class file dynamically.  Also, note that from JDBC 4.x onwards, loading the driver becomes optional as the JVM takes care of loading the driver to classpath.  So, you don' t need to explicitly invoke the Class.forName() method.

Create the connection

Once the drivers are loaded, you have to create a connection to the specific database by providing the database URL as shown below.
Connection connection=DriverManager.getConnection("jdbc:oracle:thin:username/password@10.120.79.57:1521:georli01"); 
The getConnection() method of java.sql.DriverManager class is used to create a connection between Java application and database. This connection is represented by the instance of java.sql.Connection. The getConnection() method accepts the database URL either in a single argument or in three different arguments as shown below.
In our code we have used the single argument getConnection() method.
When getConnection() is invoked, java.sql.DriverManager will try to locate a suitable driver among the loaded drivers, and the connection is established through the selected driver upon verifying the credentials
Within an application, we can have more than one connection with a single database, or multiple connections with multiple databases.

Prepare the statement

Once the connection is established, the application can query the database. To do so, an object of java.sql.PreparedStatement is required. It represents a precompiled SQL statement. The java.sql.Connection provides prepareStatement() method to create a PreparedStatement object as shown below.
String sql = "select * from customer where customerName='George'";
PreparedStatement pStatement = connection.prepareStatement(sql);
The method accepts the SQL command as a String. During execution, this SQL command is given to the DBMS and will be compiled there. Later, when the PreparedStatement object is executed using JDBC methods, which we will be discussing shortly, the DBMS can directly run the SQL command, without having to compile it again.

Prepare the statement: SQL Injection Attack

Since we write the SQL statements as String in our JDBC application, we can pass some dynamic values at run time and concatenate it with the query as shown below:
String customerName = "George";
PreparedStatement pStatement=connection.prepareStatement("SELECT * FROM customer WHERE customerName='"+customerName+"'");
Now, the SQL statement fired to database will be
SELECT * FROM customer WHERE customerName='George'
Is there any issues in this code?
Yes, the main problem here is security. But why?
Consider the customerName is an user entered value. Now a hacker comes in and he enters the value of customerName as,
8
What will be the result of above query?
  • This will fetch all the rows present in the table because ‘1’=‘1’ is always true. From this, a hacker can get the details of all the customers.
  • Think if hacker injects these type of values with InfyBank's Login table, he gets all the credentials and he may misuse it.
It is a serious security issue for InfyBank.
Inserting such malicious SQL statements into application is known as SQL injection attack.

According to OWASP's (Open Web Application Security Project) Top 10 security risks, Injection attack is the most critical security vulnerability in application security risks. OWASP is an open community to educate, build tools and create awareness for the major security issues of an web application. To know more about OWASP Top 10 security risks

Prepare the statement: Solution for SQL Injection Attack

Observe the code given below where dynamic values are passed as parameters to the query:
String sql="SELECT * FROM customer WHERE customerName=?";                  //indicates position of parameter
PreparedStatement pStatement=connection.prepareStatement(sql);
pStatement.setString(1, customerName);                                     //setting the parameter value
Here ‘?’  is used in the query to indicate the position of parameter which starts from 1(one). The parameter can be bound with a value using setXXX(parameterIndex, value) of PreparedStatement, where XXX represents the Java data type of the parameter that we wish to bind.
Below is a sample query consisting of multiple parameters.
String sql="SELECT * FROM customer WHERE customerid=? AND customername=?";
PreparedStatement pStatement=connection.prepareStatement(sql);
pStatement.setInt(1, customerId);
pStatement.setString(2, customerName);
These type of queries where parameters are set in run time using parameter index is called as Parameterized queries. This is the solution for SQL injection attack.
It helps in preventing such malicious attack as the binding parameters are loaded dynamically at run time. Let us see how does it help your code..
String sql="SELECT * FROM customer WHERE customerid=? AND customername=?";
PreparedStatement pStatement=connection.prepareStatement(sql);
pStatement.setInt(1, customerId);
pStatement.setString(2, customerName);
As we set the parameters using type of parameters itself (i.e. setXXX()), it will consider the whole value as of that type.
  • Suppose if a hacker supplies customerId as 10 or '1'='1', it will be a compilation error as Integer will not accept the String value.
  • If hacker supplies customerName as John' or '1'='1, it will take whole thing as String and it will search for customer whose customerName is exactly "John' or '1'='1"
The advantage of  PreparedStatement is, it is compiled once and kept ready with an execution plan, which can be reused several times with different parameters and it increases the performance of the application.

Execute the Statement

Based on database operations, queries can be categorized in two types:
  • Queries to retrieve the value - select
  • Queries to manipulate the values in database - insert, update and delete
PreparedStatement provides two different methods to execute these two types of queries:
  • executeQuery()
  • executeUpdate() (will be discussed later)
executeQuery() method is used to execute the queries which retrieves the data from database like Select. This returns a ResultSet object holding all the retrieved data. The resultSet will be discussed in next step.
String sql="SELECT * FROM customer WHERE customerName='George'";
ResultSetPreparedStatement pStatement=connection.prepareStatement(sql);
ResultSet resultSet=pStatement.executeQuery();

Process the result

The executeQuery() method returns the object of java.sql.ResultSet which represents the resultant table fetched from database during a retrieval operation.
Look into the below code:
String sql="SELECT * FROM customer WHERE customerName='George'";
ResultSetPreparedStatement pStatement=connection.prepareStatement(sql);
ResultSet resultSet=pStatement.executeQuery();
while(resultSet.next()){                                          
       Integer id=resultSet.getInt(1);
       String customerName=resultSet.getString("customerName");
       String city=resultSet.getString("city");
       Long phoneNumber=resultset.getLong(4);
}
ResultSet maintains a cursor pointing to one row of data in the resultant table.
Initially, the cursor is positioned before the first row and can be moved to the next position using next() method of ResultSet. When next() is invoked, it forwards the cursor by one row and returns true if the cursor is at a valid row. Else it will return false. By default, the ResultSet cursor can move only in forward direction.
ResultSet provides getXXX() method as well to read the individual column values from the resultant table.
Let us see how to use the next() and getXXX() methods to process the ResultSet of the above code….
 Retriving the result from cursor

Inserting Data Into Database using execute Update
Below is the sample JDBC code to insert the customer details into CUSTOMER table.  Observe the highlighted part of the code.
public class CustomerDAO {
  public void addCustomer()throws Exception{
       String sql="Insert into customer values(?,?,?,?)";
        //1. JDBC driver is loaded implicitly 
        try (Connection connection=DriverManager.getConnection("jdbc:oracle:thin:username/password@10.120.79.57:1521:georli01");  
             PreparedStatement pStatement=connection.prepareStatement(sql)){     // 2 & 3. creates Connection and PreparedStatemet instance
                 pStatement.setInt(1,1001);
                 pStatement.setString(2,"John");
                 pStatement.setString(3,"Mysore");
                 pstatement.setLong(4,9213456780l);   
                 int rowsAffected=pStatement.executeUpdate();                    //4. executes the statement 
                 if(rowsAffected>0){                                             //5. processes the result
                    System.out.println(rowsAffected + " row inserted successfully ");
                 }
            } catch (SQLException exception) {          
                 throw exception;
            }  catch (Exception exception) {
                 throw exception;
          }
     }
 }
The steps used to insert a record are same as the steps involved in retrieving record except the method used in fourth step '4.execute the statement'
Here, you may have observed that we are using executeUpdate() method for executing the insert operation. This method is mainly used to execute the queries like insert, update, delete which manipulates the values in database. This method returns the number of rows effected due to query execution.
JDBC API - an overview
Below are the important classes and interfaces you used in your JDBC application to perform the CRUD operations. All these classes and interfaces are available under java.sql package
12
DriverManager class – Used to manage the driver classes loaded in the application. It provides methods to establish a connection with the database by choosing an appropriate driver class
Driver interface – Used by database vendors to implement driver class
Connection interface – Represents the connection with the database. It provides methods to create query statements
PreparedStatement interface – Represents the SQL statement for database operation
ResultSet interface – Represents the resultant table obtained from database
From JDBC to ORM framework
By now, you have learnt how to implement data persistence using JDBC API. But, JDBC is not the most suitable option for an enterprise application. The main reasons are,
  • The persistence part of the application (CustomerDAO.java) repeats some steps like loading driver, establishing connection, etc., which leads to a lot of repetitive code
  • Most of the code in a Java enterprise application will be object-oriented. But, when it comes to persistence using JDBC, the style changes from object-oriented to relational way. We manually map the object’s properties with a relational table’s columns and construct a query to perform database operation as given below
    • Construct query string with values extracted from object
      String sql="SELECT * FROM customer WHERE customerid=? AND customername=?";
      PreparedStatement pStatement=connection.prepareStatement(sql);
      pStatement.setInt(1, customer.getcustomerId());
      pStatement.setString(2, customer.getcustomerName());
      
    • Manually iterate through the Resultset object returned by database to extract the data
  • You should be aware of the query language of the underlying database
  • Migrating from one database to another, for example from Oracle to MySQL,  becomes difficult as the JDBC application uses database specific query language in it

Using an Object Relational Mapping (ORM) framework is one of the best solutions to solve such issues.  Let us discuss about ORM in detail.

Object-Relational Impedence Mismatch

The major problem in JDBC is, it needs to take care of the fundamental differences in the way Object Oriented Programs(OOP) and RDBMS deals with the data.
  • In Object Oriented Programming language like Java, the data is stored as hierarchical and interrelated objects.
  • In relational database, the data is stored in a tabular format or relations.
Storing and retrieving Java objects in and from relational database exposes a paradigm mismatch called 'Object-Relational Impedance Mismatch'. These differences are because of perception, style and patterns involved in both the paradigms that leads to following paradigm mismatches:                    
  • Granularity: Mismatch between the number of classes in object model and number of tables in relational model
  • 13
  • Inheritance or Subtype: Inheritance is an object oriented paradigm which is not available in RDBMS
  • 14
  • Aggregation: In object oriented programming, aggregation is represented using reference variables, whereas, in relational model foreign keys are used for aggregating two tables
  • 15
  • Identity: In Java, object equality is determined by '=='  operator or 'equals()' method, whereas, in RDBMS primary key is used to uniquely identify the records
  • 16
  • Data Navigation: In Java, dot(.) operator is used to travel through object network, whereas, in RDBMS join operation is used to navigate between related records
  • 17
Object Relational Mapping - Solution for Object-Relational Impedance MismatchObject Relational Mapping (ORM) is a technique or design pattern, which maps object oriented paradigm with relational paradigm.

Features of ORM

  • Resolves the Object-Relational Paradigm mismatch by mapping
    • Java classes to database tables
    • Instance variables to columns
    • Objects to rows in the table
  • The lower level interaction with database is handled by the ORM. Framing and executing the database dependent queries is taken care by the ORM framework.
  • Helps the developer to get rid of “messy SQL”. The developer need not have to waste time in writing the plumbing code. They can concentrate on the business logic and work with the object model.
  • ORM is database independent. All database vendors provide support for ORM. Hence, the application becomes portable without worrying about the underlying database.


ORM frameworks are preferred as an elegant persistence solution for enterprise applications. There are a lot of ORM frameworks like JPA, Hibernate, etc. available in the market from different vendors. Each framework maps the OO paradigm with relational paradigm in its own way. We are going to discuss about Java Persistence API (JPA).
What is Java Persistence API?
Many third party persistence frameworks like Hibernate, EclipseLink, were available in market, which helped the developers to achieve Object-Relational Mapping and perform database operation in object oriented approach. But, it became challenging to port application from one ORM framework to another as every framework addressed the paradigm mismatch in its own way.
In 2006, JPA was released by Java Community Process, to standardize the persistence process. JPA incorporated many features from the existing frameworks like Hibernate and TopLink Essentials.
JPA became the standard specification for ORM in Java. As the name indicates, JPA is just a specification (having set of interfaces), which provides the standards and specification to be followed while mapping the Java objects and the database objects.
There are multiple providers available in market like EclipseLink, OpenJPA, Hibernate, etc. giving implementations to the JPA specification
18
We will be using the implementation provided by Hibernate.
Let us start using JPA to implement data persistence in our application.
The Java Persistence API is available in javax.persistence package
Persisting Customers for InfyBank
Assume that you are asked to implement InfyBank application using JPA as your data persistence technology.  You are asked to persist the customer details into CUSTOMER table using JPA.  The table structure is shown below.
Implement the below files in a JPA project to solve the above InfyBank requirement.
Customer.java
@Entity
public class Customer {
@Id
private Integer customerId;
private String customerName;
private Long phoneNumber;

\\getters and setters
}
persistence.xml

CustomerDAO.java
public class CustomerDAO {
 public void addCustomer() throws Exception {
  EntityManagerFactory entityManagerFactory=null;
  EntityManager entityManager = null;
  Customer customer = null;
  try {
   // Creating EntityManageFactory using same persistence unit name mentioned in persistence.xml
   entityManagerFactory=Persistence.createEntityManagerFactory("Demo");

   // Creating Entity Manager
   entityManager = entityManagerFactory.createEntityManager();

   // Creating and Populating the Customer instance
   customer=new Customer();
   customer.setCustomerId(5004);
   customer.setCustomerName("Raj");
   customer.setContactNumber(9865795715l);
   
   // Making a transaction Object
   EntityTransaction entityTransaction = entityManager.getTransaction();

   // Beginning the transaction
   entityTransaction.begin();

   // Persisting the customer object into database
   entityManager.persist(customer);

   // Transaction completion is done using this statement and all the scheduled database updates will be reflected 
   entityTransaction.commit();

                        System.out.println("Added a customer successfully");
  } catch (Exception exception) {
   System.out.println("Error:"+exception.getMessage());
  }
  finally {
   if (entityManager != null) {
    entityManager.close();
   }
   if (entityManagerFactory != null) {
    entityManagerFactory.close();
   }
  }
 }
}
If you invoke addCustomer() method of CustomerDAO.java from the main() method and execute it, a record will get inserted in the CUSTOMER table.
The steps used in this project are:
  1. Create a JPA project
  2. Create Entity class (Customer.java)
  3. Configure persistence.xml
  4. Perform persist operation (CustomerDAO.java)
Let us discuss each step in detail...

2. Create entity class: @Entity and @Id

As you already know, the ORM resolves the paradigm mismatch by mapping the class with a table, you need a Customer class for your InfyBank application which can be mapped with the given CUSTOMER table.  The class which can be mapped with a database table and can be persisted is referred as an ‘Entity’ class in JPA. 
To create an entity class
  • The class should have a public or protected, no-argument constructor. It may have other constructors.
  • The class should not be a final class and it should not have any final members.
  • The instance variables should be declared as private or protected and should have corresponding public getters and setters methods.
  • The class should be annotated with JPA annotations.
Below is the Customer entity class which can be mapped with CUSTOMER table
19
Observe that the class name is same as the table name and the instance variables names are same as the column names.  JPA maps the class with the appropriate table by matching their name and data type with each other.  The java data type that you used in the entity class should be compatible with the respective column's data type.
Let us discuss about the annotations used in the code that turns the regular Customer bean object into an entity object.
@Entity and @Id are the minimum set of annotations to be used for creating an entity class.

@Entity

It is a class-level annotation. The POJO class which needs to be mapped with the database table should be annotated by this annotation. It enables the class to be serializable, and hence we will be able to read/write the state of the class from/to the database.  In the above code, @Entity maps the Customer class with CUSTOMER table and enables the class for persistence.

@Id

It is a field-level annotation. This should be applied on the attribute of the class that needs to be mapped with the primary key column of the table.  Since customerId is the primary key column in CUSTOMER table, the corresponding attribute in Customer class is annotated by @Id.

3. Configure persistence.xml

After mapping the POJO class Customer.java with CUSTOMER table, you will be able to give instructions to JPA framework in terms of objects of Customer to perform the database operations.
Internally, the JPA framework, converts these instructions into database specific SQL queries and executes them.
So, the JPA framework needs to be configured to hit the database with the right credentials and generate SQL queries in the required dialect. These configuration details should go inside a xml file named persistence.xml file. When the JPA application is started up, the framework will refer this xml file to establish the database connection and to map the entity class with the appropriate database tables. 
The basic structure of persistence.xml is given below.
Let us discuss about the different sections of persistence.xml in detail.

per.img

Persistence unit

persistence.xml file starts with defining a persistence unit which specifies the rest of the configuration details. When an application needs to connect to multiple databases, the persistence.xml file can contain multiple persistence-units, each specifies the configuration for a specific database. Each persistence unit is uniquely identified by it’s name. In our example, we have named the persistence unit as 'Demo'.
Persistence unit also talks about transaction management. When the transaction type is ‘RESOURCE_LOCAL’, it indicates that the transactions are managed locally within the persistence unit. Another possible transaction-type can be ‘JTA’, which is not covered in this course.

Provider

The provider element is used to define the implementation provider details.  In our application, we are using the JPA implementation provided by Hibernate.

Class

The class element is used to list the entity classes so that the entity class can be mapped with the appropriate tables in the database.  The CustomerEntity class which you have created before has to be listed here with its fully qualified class name as shown below.

Property

The property element is used to list the database configuration details like database URL, credentials, driver details and database schema generation details. The code below enables your application to interact with Georli01 Oracle database server.
Observe the schema-generation property configured in persistence.xml. This property can be configured to generate database tables through the framework if required. As of now, with value as none, the framework will not try to create any tables. Instead, it will map the entity objects with the existing schema.

Note:  As the database configuration details are isolated in persistence.xml configuration file, the JPA applications are easily portable across databases.  

4. Perform persist operation

Having mapped your entity class and configured your database related details with JPA framework, you can now give instructions in terms of the entity objects to perform the database operation.
The steps used in CustomerDAO.java to perform the persist operation are:
  1. Create instance of EntityManagerFactory and EntityManager
  2. Define a transaction context
  3. Populate and persist the entity object inside an active transaction
  4. Close EntityManager and EntityManagerFactory
Let us discuss each step in detail..

4.1. Create instance of EntityManagerFactory and EntityManager

EntityManagerFactory
It is a factory class used to create EntityManager objects. EntityManagerFactory object is obtained by using the static createEntityManagerFactory() method of Persistence class. Implement CustomerDAO.java as shown below for EntityManagerFactory creation.
public class CustomerDAO {
 public void addCustomer() throws Exception {
  EntityManagerFactory entityManagerFactory=null;
  EntityManager entityManager = null;
  Customer customer = null;
  try {
   // creates EntityManageFactory instance using same persistence unit name defined in persistence.xml
   entityManagerFactory=Persistence.createEntityManagerFactory("Demo");

                        //......

        } catch (Exception exception) {  
   throw exception;
  }  
 }
}
Here, the String argument 'Demo' represents the persistence unit name defined in persistence.xml. The persistence unit name gives the application the details about the database and the entities on which it can operate.  Since EntityManagerFactory is a heavy weight object as it is maintaining a pool of EntityManager objects and database connections, it is recommended to create only one EnityManagerFactory object per persistence unit.
In our persistence.xml, the persistence unit 'Demo' is configured with Oracle database and CustomerEntity.java, and hence entityManagerFactory is connected with Oracle database and can operate on CustomerEntity object. 
EntityManager 
It represents the database connection. Add the below highlighted code in CustomerDAO.java to obtain EntityManager object.
public class CustomerDAO { 
     public void addCustomer() throws Exception {
            EntityManagerFactory entityManagerFactory=null; 
            EntityManager entityManager = null; Customer customer = null; 
            try { 
                   entityManagerFactory=Persistence.createEntityManagerFactory("Demo"); 
                   //creates instance of EntityManager    
                   EntityManager entityManager = entityManagerFactory.createEntityManager();

                    //......   

            } catch (Exception exception) { throw exception; } 
    } 
}
Many EntityManager objects can be created from a single EntityManagerFactory.  Generally, a EntityManager object will be created per database transaction.
The EntityManager provides following methods to perform CRUD operations and to manage the entity objects:
  • public void persist(Object entity) - to insert a record
  • public Object find(Entity.class, Object primaryKey) - to retrieve a specific record
  • public void remove(Object entity) - to delete a record
Note: Only persist() is discussed in this course.

4.2 Define a transaction context

Any operation which modifies the database content, such as insert, update and delete requires a transaction context in your application.  As you are doing an insert operations which modifies the database content by inserting a new row, you need to define a transaction in your application.
EntityTransaction interface manages the database transactions in JPA. It provides the following methods to manage the transaction:
public void begin() – Begins a transaction
public void commit() – Commits the transaction changes to the database
public void rollback() – Rolls back or aborts the current transaction
In order to perform your insertion operation, you have to add code in CustomerDAO.java to create an EntityTransaction object, begin the transaction, perform the insert(persist) operation and commit the transaction as shown below.
public class CustomerDAO { 
     public void addCustomer() throws Exception {
            EntityManagerFactory entityManagerFactory=null; 
            EntityManager entityManager = null; Customer customer = null; 
            try { 
                   entityManagerFactory=Persistence.createEntityManagerFactory("Demo");                     
                   EntityManager entityManager = entityManagerFactory.createEntityManager();
                   // creates an EntityTransaction instance
                   EntityTransaction entityTransaction = em.getTransaction();                  
                   entityTransaction.begin(); 

                   //code to persist

                   entityTransaction.commit();        
                   
           } catch (Exception exception) { throw exception; } 
    } 
}

4.3 Populate and persist the entity object inside an active transaction

The persist() method of EntityManager should be invoked to persist your entity object (CustomerEntity.java).  The persist() method will in turn insert a record into the corresponding table with values available in entity object.
Add below highlighted code in CustomerDAO.java  to populate CustomerEntity and to persist it.
public class CustomerDAO {
 public void addCustomer() throws Exception {
  EntityManagerFactory entityManagerFactory=null;
  EntityManager entityManager = null;
  Customer customer = null;
  try {   
   entityManagerFactory=Persistence.createEntityManagerFactory("Demo");   
   entityManager = entityManagerFactory.createEntityManager();

   // Creating and Populating the CustomerEntity instance
   customer=new Customer();
   customer.setCustomerId(5804);
   customer.setCustomerName("Raj");
   customer.setContactNumber(9865795715L);   
   
   EntityTransaction entityTransaction = entityManager.getTransaction();   
   entityTransaction.begin();

   // persistence of the customer
   entityManager.persist(customer);
   
   entityTransaction.commit();
            System.out.println("Customer added successfully");
  } catch (Exception exception) {  
   throw exception;
  }
   }
}
Observe in the code that persist() method is invoked inside an active transaction( in between begin() and commit()). Invoking the persist() method makes the customer object persistent.  When the commit() is invoked, the object is physically inserted into the corresponding table as a record.

4.4 Close EntityManager and EntityManagerFactory

Once your database transaction is done, it is recommended to close the EntityManager so that the resources held by it, such as database connection and entity objects, becomes free.  
Similarly, the EntityManagerFactory should also be closed when your application no longer needs it.  When the EntityManagerFactory is closed, all EntityManagers from that factory are closed and all the entities managed by those EntityManagers become invalid.
public class CustomerDAO {
 public void addCustomer() throws Exception {
  EntityManagerFactory entityManagerFactory=null;
  EntityManager entityManager = null;
  Customer customer = null;
  try {   
   entityManagerFactory=Persistence.createEntityManagerFactory("Demo");   
   entityManager = entityManagerFactory.createEntityManager();   
   customer=new Customer();
   customer.setCustomerId(5804);
   customer.setCustomerName("Raj");
   customer.setContactNumber(9865795715L);
   EntityTransaction entityTransaction = entityManager.getTransaction();   
   entityTransaction.begin();   
   entityManager.persist(customer);   
   entityTransaction.commit();
                        System.out.println("Customer added successfully");
  } catch (Exception exception) {  
   throw exception;
  }finally {
   if (entityManager != null) {
    entityManager.close();
   }
   if (entityManagerFactory != null) {
    entityManagerFactory.close();
   }
  }
   }
}
Now you have completed all the steps in implementing the requirement of persisting customers.
JPA: Further Essential Annotations
Assume that InfyBank has made some changes in its business requirements and has given an updated version of CustomerEntity class and the CUSTOMER table to implement persistence.
public class CustomerEntity {
    private Integer customerId;
    private String customerName;
    private Calendar dateOfBirth;
    private String address;
    private Long contactNumber;
    //getters and setters
}
         
Observing the above CustomerEntity class and the CUSTOMER table, we can find some challenges among them:
  • The class name and the table name is different
  • The attribute name is contactNumber in the class, but the column name in table is phoneNumber
  • The data type of dateOfBirth is java.util.Calendar in the class, but is sql.Date in the table
  • Entity class is having an address variable for which there is no corresponding column in the table
Can you still map the class with the table?  
Yes, you can.  You need to use few more JPA annotations to resolve the name and datatype mismatch.
Below are the annotations to be used in CustomerEntity class to map it with CUSTOMER table.
@Entity
@Table(name="customer")
public class CustomerEntity {
    @Id
    private Integer customerId;
    private String customerName;
    @Temporal(TemporalType.DATE)
    private Calendar dateOfBirth;
    @Transient
    private String address;
    @Column(name="phoneNumber")
    private Long contactNumber;
    
    //getters and setters()
}
The details of annotations used in the code are:
20
JPA: An Overview
21
  • javax.persistence.Persistence - Class which helps in creating the EntityManagerFactory instance.
  • javax.persistence.EntityManagerFactory - Interface which helps in managing connections by creating and managing the EntityManager objects
  • javax.persistence.EntityManager - Interface which represents single conenction between the application and the database, and provides methods to perform database operations
  • javax.persistence.EntityTransaction – Inteface which manages unit of work to be performed which modifies the database values
  • Persistence unit - persistence.xml file defines a persistence unit which specifies the configuration details
  • Entity - a java class which is mapped with the respective table in the database









Featured Post

HTML cheetsheet

List: Link tgs Dropdown

Popular Post

(C) Copyright 2018, All rights resrved InShortView. Template by colorlib