Spring Data JPA Introduction

Spring Data JPA Introduction | First let us see the difference between JDBC, JPA, Hibernate, and Spring Data JPA.

  • JDBC works based on SQL Query, given by Programmer.
  • JPA (Specification given by Sun/Oracle), generates all SQLs based on operations.
  • For a Specification, we must follow one implementation ie Hibernate.
  • Even in Hibernate, the programmer has to do code manually for operations, transactions, pooling, etc.
  • In Spring Data JPA, code is automated. It internally follows Hibernate with the JPA concept.
  • If we compare JDBC-Project and JPA-Project, the number of lines of code inside JPA is less. Even error rate also. Whereas in JDBC manual SQL coding is required.
  • We can not write code using only JPA, internally one Impl must be there.
  • In JPA also some coding lines exist. Spring Data JPA can reduce them into a few lines.
  • The difference between JPA (with Hibernate) and Spring Data JPA is the number of lines of code only. Spring Data JPA reduces coding lines.

Spring Data JPA:-

  1. Programmers need not to define code for basic database operations. Just provide model class/entity class and primary key with data type.
  2. It supports embedded databases like H2, HyperSQL (HSQL), Aoache Darby) so no download & installation is required. They are embedded/InMemory database/RAM database. Therefore, it is used only for development purposes, never used in production.
  3. It also supports custom query programming using findBy, and @Query(JPQL/HQL, SQL).

Annotation:-

  • @Entity: It maps our class with the database table.
  • @Id: It indicates the primary key.
  • @Table: To provide table details like name. It is optional, if we don’t provide the table name then class-name will become the table name.
  • @Column: To provide column details we can use this like column-name. It is optional. If we do not provide a column name, the default is variable-name.

Example of Using H2 Database

Use the spring starter to create the project and add the following dependencies:- Spring Data JPA, Lombok, Spring Web, and H2 database. To work with the H2 database, its dependency is required.

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

Model class:-

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
@Table(name = "emp")
public class Employee {
    @Id
    @Column(name = "eid")
    Integer empId;
    
    @Column(name = "ename")
    String empName;
    
    @Column(name = "esal")
    Double empSal;
}

In application.properties file:-

spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb

spring.jpa.show-sql=true

Run the application and Enter the URL as:- http://localhost:8080/h2-console/
Click on Connect (if failed modify JDBC URL=jdbc:h2:mem:testdb)

Connect H2 Database

After the successful connection, we can see the tables.

H2 Database

Spring Data JPA (DB Operations)

Datasource connection properties:-

spring.datasource.driver-class-name=
spring.datasource.url=
spring.datasource.username=
spring.datasource.password=

JPA Properties:-

spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
  1. show-sql: It is a boolean property. The default value is false. If we set it to true, then the generated SQL is displayed in the console.
  2. Database Platform/Dialect: Dialect is a class that generates SQL queries when we perform the DB operation. Dialect classes exist in the package org.hibernate.dialect. Every database will have its own dialect. Adding dialect is optional, Spring will be able to configure them itself based on the given database.
  3. ddl-auto:- create/update/validate/create-drop
    • ddl-auto=create: When we run the application, it creates new tables. If already old tables exist then drop them and create a new one.
    • ddl-auto=update: When we run the application, it will check for old tables. If exist use the same, else create new tables.
    • ddl-auo=validate (or none): In this case, the application will not create/drop/alter. The programmer has to define manual SQL queries.
    • ddl-auto= create-drop: When we start the application:-
      • Drop Tables if exist.
      • Create new tables.
      • Perform DB operations.
      • At the end again drop tables.

For ddl-auto validate(none) is the default value for the external database. If we use embedded DB (like H2) then the default is create-drop.

SQL queries are database-dependent. If we write one SQL query for Oracle, it may/may not work for SQLServer DB. Dialect solves the above problem by generating queries at runtime. So, the dialect is different for every DB.

Spring Data JPA Example

For your Module (Ex: Employee, Admin, Student ..etc) You do not have to define operations code. Just define interface, that must implement one of the below interfaces:-

  1. CrudRepository<T, ID>
  2. PagingAndSortingRepository<T, ID>
  3. JpaRepository<T, ID>

At the runtime a class will be generated which will contain all the database operation logic.

Coding files:-

  • Model class/Entity class
  • Repository Interface
  • Runner class for Testing operations

In this example we will use MySQL table,

mysql> show databases;
mysql> create database test;
mysql> use knowprogram;
mysql> show tables;
mysql> select * from emp;

Properties file:-

# datasource properties
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root

#jpa properties
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create

Entity Class:-

package com.knowprogram.demo.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;

@Data
@Entity
@Table(name = "emp")
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer empId;

    @Column(name = "ename")
    private String empName;

    @Column(name = "esal")
    private Double empSal;
}

Which DataType can be used to create primary key variable in Hibernate/JPA? Any class which is serializable can be used as primary key.

Repository:-

T = Model className = Employee
ID = DataType(of PrimaryKey) = Integer

package com.knowprogram.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.knowprogram.demo.model.Employee;

public interface EmployeeRepository extends JpaRepository<Employee, Integer> {

}

Runner Class:-

package com.knowprogram.demo.runner;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.knowprogram.demo.model.Employee;
import com.knowprogram.demo.repository.EmployeeRepository;

@Component
public class TestRunner implements CommandLineRunner {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Override
    public void run(String... args) throws Exception {
        Employee emp = new Employee();
        emp.setEmpName("ABC");
        emp.setEmpSal(200.0);
        employeeRepository.save(emp);
    }

}

It will use these queries:-

Hibernate: drop table if exists emp
Hibernate: create table emp (emp_id integer not null auto_increment, esal float(53), ename varchar(255), primary key (emp_id)) engine=InnoDB
Hibernate: select e1_0.emp_id,e1_0.ename,e1_0.esal from emp e1_0 where e1_0.emp_id=?
Hibernate: insert into emp (ename,esal) values (?,?)
MySQL Database

Hibernate Vs Spring Data JPA

If we use Hibernate we should write code manually.

// Hibernate 5 with JPA 
try {
    EntityManagerFactory emf = HibernateUtil.getEmf();
    EntityManager em = emf.createEntityManager();
    EntityTransaction et = em.getTransaction();
    et.begin();
    Employee obj= new Employee();
    ...
    em.persist(obj);
    et.commit();
} catch(Exception e) {
    sysout(e);
    et.rollback();
}

In Hibernate F/w Programmer is writing code for operations manually. Now same code is going to be generated by Spring Data JPA. But it is asking for two inputs:-

  1. Model class Name = T = Employee
  2. PrimaryKey DataType = ID = Integer
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
}

At runtime, one class is generated using your inputs, ie called Proxy. (Dynamic Proxy).

class $1 implements EmployeeRepo {
    public <S extends Employee> S save(S entity) {
        Assert.notNull(entity, "Entity must not be null.");
        if (entityInformation.isNew(entity)) {
            em.persist(entity);
            return entity;
        } else {
            return em.merge(entity);
        }
    }
}
  • S extends Employee means: Employee object or its sub-class objects are allowed.
  • S super Employee means: Employee objects or its superclass objects are allowed.

If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!

Leave a Comment

Your email address will not be published. Required fields are marked *