Spring Data JPA CRUD Example Tutorial

In this tutorial, we will learn how to perform CRUD operations using Spring Data JPA with MySQL database.

We will create a new Spring Boot 3 project to demonstrate the Spring Data JPA CRUD example.

Learn and master Spring Data JPA at Spring Data JPA Tutorial

Spring Data JPA Overview

We can use Spring Data JPA to reduce the amount of boilerplate code required to implement the data access object (DAO) layer.

Spring Data JPA is not a JPA provider. It is a library/framework that adds an extra layer of abstraction on top of our JPA provider (like Hibernate).

Spring Data JPA provides repositories so we just need to extend them to get full the out-of-the-box implementation for CRUD operations for an entity.

In this tutorial, we will perform CRUD operations for the Product entity and we gonna use the MySQL database to store and retrieve the data.

Adding Maven Dependencies

Let's first add the required dependencies to use Spring Data JPA into our maven project:

                <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>com.mysql</groupId>
			<artifactId>mysql-connector-j</artifactId>
			<scope>runtime</scope>
		</dependency>

Create Product Entity

Next, let's create a Product entity to perform CRUD database operations.

package net.javaguides.springdatajpacourse.entity;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import jakarta.persistence.*;
import java.math.BigDecimal;
import java.util.Date;

@Entity
@Table(name="products")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "sku")
    private String sku;

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

    @Column(name = "description")
    private String description;

    @Column(name = "price")
    private BigDecimal price;

    @Column(name = "image_url")
    private String imageUrl;

    @Column(name = "active")
    private boolean active;

    @Column(name = "date_created")
    @CreationTimestamp
    private Date dateCreated;

    @Column(name = "last_updated")
    @UpdateTimestamp
    private Date lastUpdated;

    // getter and setter methods

    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", sku='" + sku + '\'' +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                ", price=" + price +
                ", imageUrl='" + imageUrl + '\'' +
                ", active=" + active +
                ", dateCreated=" + dateCreated +
                ", lastUpdated=" + lastUpdated +
                '}';
    }
}
The annotations used:
@Entity: This annotation indicates that the class is a JPA entity and should be managed by the persistence context.

@Table: This annotation specifies the name of the table to which the entity is mapped.

@Id: This annotation indicates that the field is the primary key of the entity.

@GeneratedValue: This annotation specifies the strategy used for generating the primary key value.

@Column: This annotation specifies the mapping of the field to the corresponding column in the database.

ProductRepository

Let's create ProductRepository which extends the JpaRepository interface:
import net.javaguides.springdatajpacourse.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product, Long> {

}
JpaRepository interface provides below methods to perform CRUD operations on a given Product entity:
  • save() method to save/update the entity to the database table
  • delete() and deleteById() methods to delete the entity from database table
  • findById() method to get the entity from the database table
  • findAll() method get all the entities from the database table
  • deleteAll() method to delete all the entities from the database table

Configure MySQL and Hibernate Properties

Let's use the MySQL database to store and retrieve the data in this example and we gonna use Hibernate properties to create and drop tables.

Open the application.properties file and add the following configuration to it:
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
spring.datasource.username=root
spring.datasource.password=Mysql@123

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect

spring.jpa.hibernate.ddl-auto = create-drop

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
Make sure that you will create a demo database before running the Spring boot application.
Also, change the MySQL username and password as per your MySQL installation on your machine.

Test CRUD Methods

Let's write the JUnit test cases to perform CRUD operations on the Product entity:

import net.javaguides.springdatajpacourse.entity.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.annotation.Rollback;

import java.math.BigDecimal;
import java.util.List;

@DataJpaTest
@Rollback(value = false)
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
class ProductRepositoryTest {

    @Autowired
    private ProductRepository productRepository;


    @Test
    void testSaveMethod() throws InterruptedException {
        Product product = getProduct1();

        // save product
        productRepository.save(product);
    }

    @Test
    void testUpdateMethod() throws InterruptedException {
        Product product = getProduct1();

        // save product
        Product savedProduct = productRepository.save(product);

        savedProduct.setName("product 1 updated");
        savedProduct.setDescription("product 1 desc updated");
        savedProduct.setPrice(new BigDecimal(300));

        // update product
        Product updatedProduct = productRepository.save(savedProduct);

        System.out.println(updatedProduct.getName());
        System.out.println(updatedProduct.getDescription());
        System.out.println(updatedProduct.getPrice());
    }

    @Test
    void testSaveAllMethod(){
        Product product = getProduct1();

        Product product2 = new Product();
        product2.setName("product 2");
        product2.setDescription("product 2 desc");
        product2.setPrice(new BigDecimal(200));
        product2.setSku("product 2 sku");
        product2.setActive(true);
        product2.setImageUrl("product2.png");

        productRepository.saveAll(List.of(product, product2));
    }

    @Test
    void testFindByIdMethod(){
        Product product = getProduct1();

        // save product
        productRepository.save(product);

        // get product by id
        Product savedProduct = productRepository.findById(product.getId()).get();

        System.out.println(savedProduct.getName());
    }

    @Test
    void testFindAllMethod(){
        Product product = getProduct1();

        Product product2 = getProduct2();

        productRepository.saveAll(List.of(product, product2));

        productRepository.findAll().forEach((p) -> {
            System.out.println(p.getName());
        });
    }

    @Test
    void testCountMethod(){
        Product product = getProduct1();

        Product product2 = getProduct2();

        productRepository.saveAll(List.of(product, product2));

        long count = productRepository.count();
        System.out.println(count);
    }

    @Test
    void testDeleteByIdMethod(){
        Product product = getProduct1();

        productRepository.save(product);

        // delete product by id
        productRepository.deleteById(product.getId());
    }

    @Test
    void testDeleteMethod(){
        Product product = getProduct1();

        productRepository.save(product);

        // delete product by id
        productRepository.delete(product);
    }

    @Test
    void testDeleteAllMethod(){
        Product product = getProduct1();

        Product product2 = getProduct2();

        productRepository.saveAll(List.of(product, product2));

        productRepository.deleteAll();
    }

    protected Product getProduct1(){
        Product product = new Product();
        product.setName("product 1");
        product.setDescription("product 1 desc");
        product.setPrice(new BigDecimal(100));
        product.setSku("product 1 sku");
        product.setActive(true);
        product.setImageUrl("product1.png");
        return product;
    }

    protected Product getProduct2(){
        Product product2 = new Product();
        product2.setName("product 2");
        product2.setDescription("product 2 desc");
        product2.setPrice(new BigDecimal(200));
        product2.setSku("product 2 sku");
        product2.setActive(true);
        product2.setImageUrl("product2.png");
        return product2;
    }
}
We are using @DataJpaTest annotation to write a JUnit test for ProductRepository methods.

@AutoConfigureTestDatabase annotation is to disable embedded in-memory database support and enable MySQL database support.

Save Product Entity

    @Test
    void testSaveMethod() throws InterruptedException {
        Product product = getProduct1();

        // save product
        productRepository.save(product);
    }

Update Product Entity

    @Test
    void testUpdateMethod() throws InterruptedException {
        Product product = getProduct1();

        // save product
        Product savedProduct = productRepository.save(product);

        savedProduct.setName("product 1 updated");
        savedProduct.setDescription("product 1 desc updated");
        savedProduct.setPrice(new BigDecimal(300));

        // update product
        Product updatedProduct = productRepository.save(savedProduct);

        System.out.println(updatedProduct.getName());
        System.out.println(updatedProduct.getDescription());
        System.out.println(updatedProduct.getPrice());
    }

Save Multiple Products

    @Test
    void testSaveAllMethod(){
        Product product = getProduct1();

        Product product2 = new Product();
        product2.setName("product 2");
        product2.setDescription("product 2 desc");
        product2.setPrice(new BigDecimal(200));
        product2.setSku("product 2 sku");
        product2.setActive(true);
        product2.setImageUrl("product2.png");

        productRepository.saveAll(List.of(product, product2));
    }

Get Product Entity By Id

    @Test
    void testFindByIdMethod(){
        Product product = getProduct1();

        // save product
        productRepository.save(product);

        // get product by id
        Product savedProduct = productRepository.findById(product.getId()).get();

        System.out.println(savedProduct.getName());
    }

Get All Product Entities

    @Test
    void testFindAllMethod(){
        Product product = getProduct1();

        Product product2 = getProduct2();

        productRepository.saveAll(List.of(product, product2));

        productRepository.findAll().forEach((p) -> {
            System.out.println(p.getName());
        });
    }

Delete Product Entity

    @Test
    void testDeleteByIdMethod(){
        Product product = getProduct1();

        productRepository.save(product);

        // delete product by id
        productRepository.deleteById(product.getId());
    }
    @Test
    void testDeleteMethod(){
        Product product = getProduct1();

        productRepository.save(product);

        // delete product by id
        productRepository.delete(product);
    }

Delete All Products

    @Test
    void testDeleteAllMethod(){
        Product product = getProduct1();

        Product product2 = getProduct2();

        productRepository.saveAll(List.of(product, product2));

        productRepository.deleteAll();
    }

Output:

Conclusion

In this tutorial, we have seen how to perform CRUD operations using Spring Data JPA with MySQL database. We have used JpaRepository interface methods such as save(), saveAll(), findById(), findAll(), delete(), deleteById(), and deleteAll() methods to perform CRUD operations on the Product entity.

Learn and master Spring Data JPA at Spring Data JPA Tutorial

Comments