Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Full CRUD with Hibernate and JPA

See in this article how to create an application (CRUD) with Hibernate and JPA

Working with database manipulation has become almost mandatory for any system, from the simplest to the most complex. Until some time ago had to use techniques and tools for performing such task very well known such as PreparedStatement DriverManager and so on.

We currently use ORM frameworks (Object-Relational Mapping) that make all the work that was previously done manually. In a nutshell a Framework ORM is responsible for abstracting a relational database, allowing you to work as if it were an object database, which is ideal for those working with a language that is already object-oriented, as is the case of Java.

In this article we will use Hibernate in conjunction with the JPA to create a basic CRUD.

Difference between Hibernate and JPA

Many confuse the difference between Hibernate and JPA. Hibernate is indeed the ORM framework, ie the physical implementation of that you will use to persist, remove, update or fetch data in the DBMS. Moreover, JPA is a layer that describes a common interface for ORM frameworks.

You can develop your entire system without JPA, only Hibernate or other ORM framework, such as TopLink. But you can not develop the system only with JPA, as it is just an interface to be used by ORM frameworks.

The general idea is to make the most abstract system possible and subject to change without major impacts. If you develop all your system using JPA with Hibernate framework and tomorrow decide to switch to TopLink, then the changes will be minimal.

Starting the construction of the project

Create a normal Java project, regardless of the IDE you are using. We must, before starting, add dependencies/libraries needed to run our project, they are:

  • hibernate-entitymanager-4.2.19.Final.jar
  • antlr-2.7.7.jar
  • dom4j-1.6.1.jar
  • hibernate-commons-annotations-4.0.2.Final.jar
  • hibernate-core-4.2.19.Final.jar
  • hibernate-jpa-2.0-api-1.0.1.Final.jar
  • Javassist-3.18.1-GA.jar
  • jboss-logging-3.1.0.GA.jar
  • jboss-transaction-api_1.1_spec-1.0.1.Final.jar
  • postgresql-9.1-903.jdbc4.jar
  • The source option at the top of this post you will find all these libraries to downloads.

Configuring the persistence.xml

Once the addition of libraries in classhpath of your project, you need a file called persistence.xml that is used by the JPA to make the important settings for the project, such as connection to the database and other extra settings that we will see in Listing 1.

Listing 1. persistence.xml

 <?xml version="1.0" encoding="UTF-8" ?>
  <persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
      version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
      <persistence-unit name="crudHibernatePU" transaction-type="RESOURCE_LOCAL">
          <provider>org.hibernate.ejb.HibernatePersistence</provider>
          <properties>
              <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
              <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
              <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/teste" />
              <property name="javax.persistence.jdbc.user" value="postgres" />
              <property name="javax.persistence.jdbc.password" value="pgadmin" />
               
              <property name="hibernate.show_sql" value="true" />
              <property name="hibernate.format_sql" value="false" />
              <property name="hibernate.use_sql_comments" value="false" />
              <property name="hibernate.jdbc.wrap_result_sets" value="false" />
              <property name="hibernate.hibernate.cache.use_query_cache" value="true" />
              <property name="hibernate.hbm2ddl.auto" value="update" />
          </properties>
      </persistence-unit>
  </persistence>

In the tag <persistence-unit> we must define the name of our persistence unit by name property which in our case is crudHibernatePU. This name is used programmatically for the JPA to know what are the settings that it should use, as a binding between the application and the persistence.xml file.

The provider tag identifies which framework we are using in conjunction with the JPA, in our case is Hibernate. Below we have several tags <property>, the hibernate.dialect defines a standard dialect of SQL commands written and jdbc.driver defines which database driver you are using, in our case the org.postgresql.Driver.

In the last three properties have the connection link to the bank, the user and finally password. For those who have worked with the DriverManager you will notice a slight resemblance to the JDBC connection that we made there.

<property name="hibernate.hbm2ddl.auto" value="update" />

This property presented configure Hibernate should cause the database to be started. In the above case we are setting its value to "update", it means that every time to start our application Hibernate will check for changes between the mapping and the database as a property added in a class. When it finds a change then Hibernate executes the DDL to update the database.

It is very important to be careful when this property is being used as it can change the database in a way that you did not want, so be sure you really need it.

You must create a directory called META-INF and place within the src directory. Within the META-INF you must place the persistence.xml.

DAO for communication with the database

The next step is to create a DAO (Data Access Object) that will communicate with the database, performing basic operations (CRUD). Every call to the application will be made to our DAO who will be responsible for communicating with the database.

Our DAO will do CRUD with a class called Customer, to see how this map our Customer class like Listing 2.

Listing 2. Customer Class, JPA Annotation

 package com..crudhibernate;
  import javax.persistence.Column;
  import javax.persistence.Entity;
  import javax.persistence.Id;
  import javax.persistence.Table;
   
  @Entity
  @Table(name = "client")
  public class Client {
   
           @Id
           private int id;
           @Column
           private String name;
           @Column
           private String regId;
           @Column
           private String rg;
           
           public int getId() {
                     return id;
           }
           public void setId(int id) {
                     this.id = id;
           }
           public String getName() {
                     return name;
           }
           public void setName(String name) {
                     this.name = name;
           }
           public String getRegId() {
                     return regId;
           }
           public void setRegId(String regId) {
                     this.regId = regId;
           }
           public String getRg() {
                     return rg;
           }
           public void setRg(String rg) {
                     this.rg = rg;
           }
  }

In addition to the default of the Customer class creation that has the attributes id, name, CPF and RG with their respective getters and setters, we also have some notes defined by the JPA:

@Entity
  @Table(name = "client")
  public class Client {

The @Entity annotation makes the JPA know that class should be handled by him, and @Table note defines that this class has a table called "client" in the database.

The first "id" attribute is a primary key and must mandatorily set @Id note that the JPA does not display errors when trying to initialize the application, the next properties have the @Column note describing these properties have a corresponding column in the bank data.

You do not need to have created the customer table with these columns, just need to have the database running. When applying the JPA itself is initialized will be responsible for creating this table with its columns if it does not exist, that because we are using the value "update" for the property hibernate.hbm2ddl.auto.

Set our Customer class, we can build the DAO responsible for making communication with the database, as shown in Listing 3.

Listing 3. Class DAO

 package com..crudhibernate;
   
  import java.util.List;
   
  import javax.persistence.EntityManager;
  import javax.persistence.EntityManagerFactory;
  import javax.persistence.Persistence;
   
  public class ClientJpaDAO {
   
           private static ClientJpaDAO instance;
           protected EntityManager entityManager;
           
           public static ClientJpaDAO getInstance(){
                     if (instance == null){
                              instance = new ClientJpaDAO();
                     }
                     
                     return instance;
           }
   
           private ClientJpaDAO() {
                     entityManager = getEntityManager();
           }
   
           private EntityManager getEntityManager() {
                     EntityManagerFactory factory = Persistence.createEntityManagerFactory("crudHibernatePU");
                     if (entityManager == null) {
                              entityManager = factory.createEntityManager();
                     }
   
                     return entityManager;
           }
   
           public Client getById(final int id) {
                     return entityManager.find(Client.class, id);
           }
   
           @SuppressWarnings("unchecked")
           public List<Client> findAll() {
                     return entityManager.createQuery("FROM " + Client.class.getName()).getResultList();
           }
   
           public void persist(Client client) {
                     try {
                              entityManager.getTransaction().begin();
                              entityManager.persist(client);
                              entityManager.getTransaction().commit();
                     } catch (Exception ex) {
                              ex.printStackTrace();
                              entityManager.getTransaction().rollback();
                     }
           }
   
           public void merge(Client client) {
                     try {
                              entityManager.getTransaction().begin();
                              entityManager.merge(client);
                              entityManager.getTransaction().commit();
                     } catch (Exception ex) {
                              ex.printStackTrace();
                              entityManager.getTransaction().rollback();
                     }
           }
   
           public void remove(Client client) {
                     try {
                              entityManager.getTransaction().begin();
                              client = entityManager.find(Client.class, client.getId());
                              entityManager.remove(client);
                              entityManager.getTransaction().commit();
                     } catch (Exception ex) {
                              ex.printStackTrace();
                              entityManager.getTransaction().rollback();
                     }
           }
   
           public void removeById(final int id) {
                     try {
                              Client client = getById(id);
                              remove(client);
                     } catch (Exception ex) {
                              ex.printStackTrace();
                     }
           }
   
  }

Our ClientJpaDAO class follows the pattern of Singleton design that ensures that only one instance of this class will be created throughout the application. When performing the creation of the class for the first time getEntityManager() method is called, responsible for creating an instance of EntityManager.

The line Persistence.createEntityManagerFactory("crudHibernatePU") uses the settings present in the persistence.xml file to create an instance of EntityManagerFactory. After that check if the entityManager attribute is null, or was never created, so we use the createEntityManager() to create an instance of EntityManager is responsible for performing CRUD operations on the database.

Everything revolves around the EntityManager, this is our main object for CRUD. Done it and understood that we need it, we can begin to create the methods they will use as attribute. Let's see GetById():

public Client getById(final int id) {
         return entityManager.find(Client.class, id);
  }

Notice the simplicity presented in the above method, the simple find() called the EntityManager passing the class type id that should be sought, already has a Customer object. If we were to use the JDBC search pattern technique, we should create a PreparedStatement that returns a ResultSet, then take the first record of the ResultSet and only then moisturize a Customer object with the ResultSet data, finally the work would be much higher, no doubt.

The next method is the finall():

 public List<Client> findAll() {
         return entityManager.createQuery("FROM " + Client.class.getName()).getResultList();
  }

It uses createQuery receiving JPQL (Java Persistence Query Language), which is an alternative to SQL in the form of object orientation, that is, you can perform queries as if the database were object-oriented.

The persist() method iInicia a transaction through getTransaction(). Begin() and ends the transaction in the commit() within this transaction runs the persist () method that saves the client object. If an error occurs then a rollback() is executed and all the changes are undone.

The merge method follows the same principle of the method persist(), the only difference is that the merge updates the record and not just insert it in the bank. But if the record does not exist in the bank and you use the merge() method it will enter the same.

Following the same principle as the others remove() method first looks for the customer in the database and only then remove. The removebyId() directly receives the ID that must be removed while the remove() receives the object.

Let's create a form to perform the insertion, deletion, update and search client, as shown in Figure 1.

Figure 1. CRUD Customer Form

Our form has four basic fields, those defined in our Customer class and three buttons for different actions.

Let's look at the actions of the three buttons, each in a different method, a ActionListener, as shown in Listing 4.

Listing 4. ActionListeners buttons

 private void jButtonSaveActionPerformed(java.awt.event.ActionEvent evt) {                                              
          Client client = new Client();
          client.setRegId(jTextFieldRegId.getText());
          client.setId(Integer.parseInt(jTextFieldID.getText()));
          client.setName(jTextFieldName.getText());
          client.setRg(jTextFieldRg.getText());
          ClientJpaDAO.getInstance().merge(client);
          clearFields();
          JOptionPane.showMessageDialog(this, "Saved successfuly !");
      }                                             
   
      private void jButtonRemoveActionPerformed(java.awt.event.ActionEvent evt) {                                               
          ClientJpaDAO.getInstance().removeById(Integer.parseInt(jTextFieldID.getText()));
          clearFields();
          JOptionPane.showMessageDialog(this, "Removed successfuly !");        
      }                                              
   
      private void jButtonSearchActionPerformed(java.awt.event.ActionEvent evt) {                                              
          int id = Integer.parseInt(JOptionPane.showInputDialog("Type the client id "));
          Client client = ClientJpaDAO.getInstance().getById(id);
          jTextFieldRegId.setText(client.getRegId());
          jTextFieldID.setText(String.valueOf(client.getId()));
          jTextFieldName.setText(client.getName());
          jTextFieldRg.setText(client.getRg());
      }                                             
   
      private void clearFields(){
         jTextFieldRegId.setText("");
         jTextFieldID.setText("");
         jTextFieldName.setText("");
         jTextFieldRg.setText("");
      }

The first jButtonSaveActionPerformed() method creates a client object hydrating it with the data filled in the form JTextFields later call the merge() method ClientJpaDAO which is responsible for inserting or updating the record. Later called the ClearFields() method that clears the fields so that the user can fill in the information of another client.

Then we have the jButtonRemoveActionPerformed() method that only takes the typed ID in JtextFieldID and passes to the removeById() method ClientJpaDAO. It is important to note that at no time are passing SQL commands, HQL or JPQL, and we could further improve the engagement level of our DAO allowing the CRUD be done with any type of object, not just you.

Then we have the jButtonSearchActionPerformed() that asks the user which the client ID and use GetById() method method to return the client object hydrated. The ClearFields() method is only to clean the jTextFields fields.

If you want to use NetBeans to build the form, you can use the code ".form" Listing 5 that will build the same layout shown in Figure 1.

Listing 5. File Code ".form"

 <?xml version="1.0" encoding="UTF-8" ?>
   
  <Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
    <Properties>
      <Property name="defaultCloseOperation" type="int" value="3"/>
    </Properties>
    <SyntheticProperties>
      <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
      <SyntheticProperty name="generateCenter" type="boolean" value="false"/>
    </SyntheticProperties>
    <AuxValues>
      <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
      <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
      <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
      <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
      <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
      <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
      <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
      <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
      <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
    </AuxValues>
   
    <Layout>
      <DimensionLayout dim="0">
        <Group type="103" groupAlignment="0" attributes="0">
            <Group type="102" attributes="0">
                <EmptySpace max="-2" attributes="0"/>
                <Group type="103" groupAlignment="0" attributes="0">
                    <Group type="102" attributes="0">
                        <Group type="103" groupAlignment="0" attributes="0">
                            <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
                            <Component id="jTextFieldID" alignment="0" min="-2" pref="242" max="-2" attributes="0"/>
                        </Group>
                        <EmptySpace type="separate" max="-2" attributes="0"/>
                        <Group type="103" groupAlignment="0" attributes="0">
                            <Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
                            <Component id="jTextFieldName" alignment="0" min="-2" pref="242" max="-2" attributes="0"/>
                        </Group>
                        <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
                    </Group>
                    <Group type="102" attributes="0">
                        <Group type="103" groupAlignment="0" attributes="0">
                            <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
                            <Component id="jTextFieldRegId" alignment="0" min="-2" pref="242" max="-2" attributes="0"/>
                        </Group>
                        <EmptySpace max="32767" attributes="0"/>
                        <Group type="103" groupAlignment="0" attributes="0">
                            <Component id="jLabel4" alignment="0" min="-2" max="-2" attributes="0"/>
                            <Component id="jTextFieldRg" alignment="0" min="-2" pref="242" max="-2" attributes="0"/>
                        </Group>
                    </Group>
                </Group>
                <EmptySpace max="32767" attributes="0"/>
            </Group>
            <Group type="102" alignment="0" attributes="0">
                <EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
                <Component id="jButtonSave" min="-2" max="-2" attributes="0"/>
                <EmptySpace max="-2" attributes="0"/>
                <Component id="jButtonRemove" min="-2" max="-2" attributes="0"/>
                <EmptySpace max="-2" attributes="0"/>
                <Component id="jButtonSearch" min="-2" max="-2" attributes="0"/>
                <EmptySpace max="32767" attributes="0"/>
            </Group>
        </Group>
      </DimensionLayout>
      <DimensionLayout dim="1">
        <Group type="103" groupAlignment="0" attributes="0">
            <Group type="102" alignment="0" attributes="0">
                <EmptySpace max="-2" attributes="0"/>
                <Group type="103" groupAlignment="1" attributes="0">
                    <Group type="102" attributes="0">
                        <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
                        <EmptySpace type="unrelated" max="-2" attributes="0"/>
                        <Component id="jTextFieldID" min="-2" max="-2" attributes="0"/>
                    </Group>
                    <Group type="102" attributes="0">
                        <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
                        <EmptySpace type="unrelated" max="-2" attributes="0"/>
                        <Component id="jTextFieldName" min="-2" max="-2" attributes="0"/>
                    </Group>
                </Group>
                <EmptySpace type="separate" max="-2" attributes="0"/>
                <Group type="103" groupAlignment="1" attributes="0">
                    <Group type="102" attributes="0">
                        <Component id="jLabel3" min="-2" max="-2" attributes="0"/>
                        <EmptySpace type="unrelated" max="-2" attributes="0"/>
                        <Component id="jTextFieldRegId" min="-2" max="-2" attributes="0"/>
                    </Group>
                    <Group type="102" attributes="0">
                        <Component id="jLabel4" min="-2" max="-2" attributes="0"/>
                        <EmptySpace type="unrelated" max="-2" attributes="0"/>
                        <Component id="jTextFieldRg" min="-2" max="-2" attributes="0"/>
                    </Group>
                </Group>
                <EmptySpace type="separate" max="-2" attributes="0"/>
                <Group type="103" groupAlignment="3" attributes="0">
                    <Component id="jButtonSearch" alignment="3" min="-2" max="-2" attributes="0"/>
                    <Component id="jButtonRemove" alignment="3" min="-2" max="-2" attributes="0"/>
                    <Component id="jButtonSave" alignment="3" min="-2" max="-2" attributes="0"/>
                </Group>
                <EmptySpace pref="25" max="32767" attributes="0"/>
            </Group>
        </Group>
      </DimensionLayout>
    </Layout>
    <SubComponents>
      <Component class="javax.swing.JLabel" name="jLabel1">
        <Properties>
          <Property name="text" type="java.lang.String" value="ID"/>
        </Properties>
      </Component>
      <Component class="javax.swing.JTextField" name="jTextFieldID">
        <Properties>
          <Property name="name" type="java.lang.String" value="jTextFieldId" noResource="true"/>
        </Properties>
        <Events>
          <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jTextFieldIDActionPerformed"/>
        </Events>
      </Component>
      <Component class="javax.swing.JLabel" name="jLabel2">
        <Properties>
          <Property name="text" type="java.lang.String" value="Name"/>
        </Properties>
      </Component>
      <Component class="javax.swing.JTextField" name="jTextFieldName">
        <Properties>
          <Property name="name" type="java.lang.String" value="jTextFieldName" noResource="true"/>
        </Properties>
      </Component>
      <Component class="javax.swing.JLabel" name="jLabel3">
        <Properties>
          <Property name="text" type="java.lang.String" value="Registration Id"/>
        </Properties>
      </Component>
      <Component class="javax.swing.JTextField" name="jTextFieldRegId">
        <Properties>
          <Property name="name" type="java.lang.String" value="jTextFieldRegId" noResource="true"/>
        </Properties>
      </Component>
      <Component class="javax.swing.JTextField" name="jTextFieldRg">
        <Properties>
          <Property name="name" type="java.lang.String" value="jTextFieldRg" noResource="true"/>
        </Properties>
      </Component>
      <Component class="javax.swing.JLabel" name="jLabel4">
        <Properties>
          <Property name="text" type="java.lang.String" value="RG"/>
        </Properties>
      </Component>
      <Component class="javax.swing.JButton" name="jButtonSave">
        <Properties>
          <Property name="text" type="java.lang.String" value="Save"/>
          <Property name="name" type="java.lang.String" value="jButtonSave" noResource="true"/>
        </Properties>
        <Events>
          <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonSaveActionPerformed"/>
        </Events>
      </Component>
      <Component class="javax.swing.JButton" name="jButtonSearch">
        <Properties>
          <Property name="text" type="java.lang.String" value="Search"/>
          <Property name="name" type="java.lang.String" value="jButtonSearch" noResource="true"/>
        </Properties>
        <Events>
          <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonSearchActionPerformed"/>
        </Events>
      </Component>
      <Component class="javax.swing.JButton" name="jButtonRemove">
        <Properties>
          <Property name="text" type="java.lang.String" value="Remove"/>
          <Property name="name" type="java.lang.String" value="jButtonRemove" noResource="true"/>
        </Properties>
        <Events>
          <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButtonRemoveActionPerformed"/>
        </Events>
      </Component>
    </SubComponents>
  </Form>

Conclusion

In this article we saw how to create a CRUD using Hibernate and JPA. We explain step by step from the creation of the design to insert, update, deletion or search records in the database.

The version of Hibernate used for this article was the 4.2.19 final and JPA 2.0, all available in "source code" option of this article.



Fabrí­cio Galdino is a software expert and has worked with IT analysis and business development for more than five years. It has extensive experience with testing, back and front-end technologies.

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login