What is Hibernate and how does it work ?
Published: 2022-03-31 22:25:19

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pwx6fqw6yf2osbl85nm0.png)
 
## What is Hibernate ?

Hibernate is an open source object relational mapping (ORM) tool that provides a framework to map object-oriented domain models to relational databases for web applications.

Hibernate ORM enables developers to more easily write applications whose data outlives the application process. As an Object/Relational Mapping (ORM) framework, Hibernate is concerned with data persistence as it applies to relational databases (via JDBC).

Hibernate enables you to develop persistent classes following natural Object-oriented idioms including inheritance, polymorphism, association, composition, and the Java collections framework. Hibernate requires no interfaces or base classes for persistent classes and enables any class or data structure to be persistent.

### JPA Provider

In addition to its own "native" API, Hibernate is also an implementation of the Java Persistence API (JPA) specification. As such, it can be easily used in any environment supporting JPA including Java SE applications, Java EE application servers, Enterprise OSGi containers, etc.

### High Performance

Hibernate supports lazy initialization, numerous fetching strategies and optimistic locking with automatic versioning and time stamping. Hibernate requires no special database tables or fields and generates much of the SQL at system initialization time instead of at runtime.

Hibernate consistently offers superior performance over straight JDBC code, both in terms of developer productivity and runtime performance.

### Scalability

Hibernate was designed to work in an application server cluster and deliver a highly scalable architecture. Hibernate scales well in any environment: Use it to drive your in-house Intranet that serves hundreds of users or for mission-critical applications that serve hundreds of thousands.

### Reliable
Hibernate is well known for its excellent stability and quality, proven by the acceptance and use by tens of thousands of Java developers.

### Extensibility
Hibernate is highly configurable and extensible.


## What is JPA - Java Persistence API

The Java Persistence API (JPA) is a specification of Java. It is used to persist data between Java object and relational database. JPA acts as a bridge between object-oriented domain models and relational database systems.

JPA is not a tool or framework; rather, it defines a set of concepts that can be implemented by any tool or framework.

Several popular implementations are **Hibernate**, **EclipseLink **and **Apache OpenJPA**. 

## Hibernate Query Language (HQL)

Hibernate Query Language (HQL) is an object-oriented query language, similar to SQL, but instead of operating on tables and columns.

`FROM Employee AS E`

### Associations with JPA and Hibernate

- many-to-one associations.
- one-to-many associations.
- one-to-one associations.
- many-to-many associations.

### Dependency Maven

```
<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-core-jakarta</artifactId>
	<version>5.5.7.Final</version>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>8.0.26</version>
</dependency>
```

resources/META-INF/persistence.xml

```
<?xml version="1.0" encoding="utf-8" ?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence" version="3.0">
    <persistence-unit name="testJPA" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.hibernateapp.entity.Customer</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test-hibernate?serverTimezone=America/Bogota"/>
            <property name="jakarta.persistence.jdbc.user" value="root"/>
            <property name="jakarta.persistence.jdbc.password" value="admin"/>
            <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/>
            <property name="hibernate.show_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>
```

### Manager JPA - EntityManager

```
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;

public class  JpaManager {
    private static final EntityManagerFactory entityManagerFactory = buildEntityManagerFactory();

    private static EntityManagerFactory buildEntityManagerFactory(){
        return Persistence.createEntityManagerFactory("testJPA");
    }

    public static EntityManager getEntityManager() {
        return entityManagerFactory.createEntityManager();
    }
}

```

### Customer entity

```
import jakarta.persistence.*;

@Entity
@Table(name="customer")
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Column(name="last_name")
    private String lastName;

    @Column(name="payment_method")
    private String paymentMethod;

    public Customer() {
    }

    public Customer(Long id, String name, String lastName, String paymentMethod) {
        this.id = id;
        this.name = name;
        this.lastName = lastName;
        this.paymentMethod = paymentMethod;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPaymentMethod() {
        return paymentMethod;
    }

    public void setPaymentMethod(String paymentMethod) {
        this.paymentMethod = paymentMethod;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", lastName='" + lastName + '\'' +
                ", paymentMethod='" + paymentMethod + '\'' +
                '}';
    }
}
```

### Create table Customer

```
CREATE TABLE `test`.`customers` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `last_name` VARCHAR(45) NULL,
  `payment_method` VARCHAR(45) NULL,
  PRIMARY KEY (`id`))
COMMENT = 'Description table customer';
```

### Insert data

```
INSERT INTO `test`.`customer` (`name`, `last_name`, `payment_method`) VALUES ('carlos', 'martinez', 'debit');
```

### Test create customer with EntityManager

```
import jakarta.persistence.EntityManager;
import com.carlos.hibernateapp.entity.Customer;
import com.carlos.hibernateapp.manager.JpaManager;

import javax.swing.*;

public class HibernateCreateCustomer {
    public static void main(String[] args) {

        EntityManager em = JpaManager.getEntityManager();
        try {

            String name = "Cristiano"
            String lastName = "Ronaldo"
            String paymentMethod= "debit"

            em.getTransaction().begin();

            Customer customerNew = new Customer();
            customerNew.setName(name);
            customerNew.setLastName(lastName);
            customerNew.setPaymentMethod(paymentMethod);
            em.persist(customerNew);
            em.getTransaction().commit();

            System.out.println("Customer id: " + customerNew.getId());
            customerFound = em.find(Customer.class, c.getId());
            System.out.println(customerFound);
        } catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            em.close();
        }
    }
}
```

### Test get by id customer with EntityManager

```
import jakarta.persistence.EntityManager;
import com.carlos.hibernateapp.entity.Customer;
import com.carlos.hibernateapp.manager.JpaManager;

import java.util.Scanner;

public class HibernateGetById {
    public static void main(String[] args) {
        Long id = "1";
        EntityManager em = JpaManager.getEntityManager();
        Customer customer = em.find(Customer.class, id);
        System.out.println(customer);

        Customer customerFound = em.find(Customer.class, id);
        System.out.println(customerFound);
        em.close();
    }
}
```

### Test customer List with EntityManager

```
import jakarta.persistence.EntityManager;
import com.carlos.hibernateapp.entity.Customer;
import com.carlos.hibernateapp.manager.JpaManager;

import java.util.List;

public class  HibernateList {
    public static void main(String[] args) {

        EntityManager em = JpaManager.getEntityManager();
        List<Customer> customers = em.createQuery("select c from Customer c", Customer.class).getResultList();
        customers.forEach(System.out::println);
        em.close();
    }
}
```

### Output

```
Hibernate: select customer0_.id as id1_0_, customer0_.last_name as last_name2_0_, customer0_.payment_method as payment_method3_0_, customer0_.name as name4_0_ from customers customer0_
id=1, name='carlos', last_name='martinez', paymentMethod='debito
```

### Test customer edit with EntityManager

```
import jakarta.persistence.EntityManager;
import com.carlos.hibernateapp.entity.Customer;
import com.carlos.hibernateapp.manager.JpaManager;

import javax.swing.*;

public class HibernateCustomerEdit {
    public static void main(String[] args) {

        EntityManager em = JpaManager.getEntityManager();
        try {

            Long id = "1";
            Customer customerEdit = em.find(Customer.class, id);

            String name = "Carlos";
            String lastName = "Martinez";
            String paymentMethod = "credit";

            em.getTransaction().begin();
            customerEdit.setName(name);
            customerEdit.setLastName(lastName);
            customerEdit.setFormaPaymentMethod(paymentMethod);
            em.merge(customerEdit);

            em.getTransaction().commit();
            System.out.println(customerEdit);
        } catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            em.close();
        }
    }
}
```

### Test customer delete with EntityManager

```
import jakarta.persistence.EntityManager;
import com.carlos.hibernateapp.entity.Customer;
import com.carlos.hibernateapp.manager.JpaManager;

import java.util.Scanner;

public class HibernateCustomerDelete {
    public static void main(String[] args) {
        Long id = "1";
        EntityManager em = JpaManager.getEntityManager();
        try {
            Customer customer = em.find(Customer.class, id);
            em.getTransaction().begin();
            em.remove(customer);
            em.getTransaction().commit();
        } catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            em.close();
        }
    }
}
```

## DAO Repository

The Data Access Object (DAO) pattern is a structural pattern that allows us to isolate the application/business layer from the persistence layer (usually a relational database but could be any other persistence mechanism) using an abstract API.

### Let's define a basic DAO

```
import java.util.List;

public interface CrudDAO<T> {
    List<T> list();
    T getById(Long id);
    void save(T t);
    void delete(Long id);
}
```

### Implement CustomerDAO

```
import com.carlos.hibernateapp.entity.Customer;
import jakarta.persistence.EntityManager;

import java.util.List;


public class CustomerDAO implements CrudDAO<Customer> {
    private EntityManager em;

    public CustomerDAO(EntityManager em) {
        this.em = em;
    }

    @Override
    public List<Customer> list() {
        return em.createQuery("select c from Customer c", Customer.class).getResultList();
    }

    @Override
    public Customer getById(Long id) {
        return em.find(Customer.class, id);
    }

    @Override
    public void save(Customer cliente) {
        if (cliente.getId() != null && cliente.getId() > 0) {
            em.merge(cliente);
        } else {
            em.persist(cliente);
        }
    }

    @Override
    public void delete(Long id) {
        Customer cliente = getById(id);
        em.remove(cliente);
    }
}
```

### Services 

#### Services interface

```
import com.carlos.hibernateapp.entity.Customer;

import java.util.List;
import java.util.Optional;

public interface CustomerService {
    List<Customer> list();

    Optional<Customer> getById(Long id);

    void save(Customer cliente);

    void delete(Long id);
}
```

#### Implement services

```
import com.carlos.hibernateapp.entity.Customer;
import com.carlos.hibernateapp.dao.CustomerDAO;
import com.carlos.hibernateapp.dao.CrudDAO;

import jakarta.persistence.EntityManager;

import java.util.List;
import java.util.Optional;

public class CustomerServiceImpl implements CustomerService {
    private EntityManager em;
    private CrudDAO<Customer> repository;

    public CustomerServiceImpl(EntityManager em) {
        this.em = em;
        this.repository = new CustomerDAO(em);
    }

    @Override
    public List<Customer> list() {
        return repository.list();
    }

    @Override
    public Optional<Customer> getById(Long id) {
        return Optional.ofNullable(repository.getById(id));
    }

    @Override
    public void save(Customer customer) {

        try {
            em.getTransaction().begin();
            repository.save(customer);
            em.getTransaction().commit();
        } catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        }
    }

    @Override
    public void delete(Long id) {
        try {
            em.getTransaction().begin();
            repository.delete(id);
            em.getTransaction().commit();
        } catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        }
    }
}
```

Source: [Hibernate](https://hibernate.org/orm/)