Spring Boot Project with Controller Layer + Service Layer + Repository/DAO Layer

In this tutorial, we will learn how to create a Spring boot project with three-layer architecture that is controller layer, service layer, and repository/DAO layer.

Spring Boot Project Three-Layer Architecture

We are going to use three-layer architecture in our Spring boot project:

Presentation layer/API Layer: This is the user interface of the application that presents the application’s features and data to the user.

Business/Service layer: This layer contains the business logic that drives the application’s core functionalities. Like making decisions, calculations, evaluations, and processing the data passing between the other two layers.

Data access object (DAO) layer: This layer is responsible for interacting with databases to save and restore application data.

Technologies used

  • Java 8+
  • Spring Boot
  • Spring Data JPA (Hibernate)
  • Maven
  • MySQL database
  • Lombok
  • Eclipse STS IDE

1. Create Spring Boot Project

We’ll use Spring initializr web tool to bootstrap our application. 

Go to http://start.spring.io

Select Java in the language section.

Enter Artifact as spring-boot-crud-example

Add WebLombokJPA, and MySQL dependencies.

Click Generate to generate and download the project.

Once the project is generated, unzip it and import it into your favorite IDE.

2. Maven Dependencies

Open the pom.xml file and confirm below dependencies are present:

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

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

3. Configure MySQL Database

Let's first create a database named "demo" in MySQL server.

Now, let's configure MySQL database URL, username, and password so that Spring Boot can create a Data source.

Open src/main/resources/application.properties file and add the following properties to it -

spring.datasource.url = jdbc:mysql://localhost:3306/demo?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
spring.datasource.username = root
spring.datasource.password = root
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update
Change spring.datasource.username and spring.datasource.password as per your MySQL installation.

Note that, I’ve set spring.jpa.hibernate.ddl-auto property to update. This property updates the database schema whenever you create or modify the domain models in your application.

4. Creating Model Layer

Create a Product class with the following content into it:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "PRODUCT_TBL")
public class Product {

    @Id
    @GeneratedValue
    private int id;
    private String name;
    private int quantity;
    private double price;
}

5. Create Repository Layer

Create ProductRepository interface with the following content into it:
import com.springboot.crud.example.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product,Integer> {
    Product findByName(String name);
}

6. Create Service Layer

Create a ProductService class with the following content into it:
import com.springboot.crud.example.entity.Product;
import com.springboot.crud.example.repository.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ProductService {
    @Autowired
    private ProductRepository repository;

    public Product saveProduct(Product product) {
        return repository.save(product);
    }

    public List<Product> saveProducts(List<Product> products) {
        return repository.saveAll(products);
    }

    public List<Product> getProducts() {
        return repository.findAll();
    }

    public Product getProductById(int id) {
        return repository.findById(id).orElse(null);
    }

    public Product getProductByName(String name) {
        return repository.findByName(name);
    }

    public String deleteProduct(int id) {
        repository.deleteById(id);
        return "product removed !! " + id;
    }

    public Product updateProduct(Product product) {
        Product existingProduct = repository.findById(product.getId()).orElse(null);
        existingProduct.setName(product.getName());
        existingProduct.setQuantity(product.getQuantity());
        existingProduct.setPrice(product.getPrice());
        return repository.save(existingProduct);
    }
}

7. Create Controller Layer

Create ProductController class with the following content into it:
import com.springboot.crud.example.entity.Product;
import com.springboot.crud.example.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class ProductController {

    @Autowired
    private ProductService service;

    @PostMapping("/addProduct")
    public Product addProduct(@RequestBody Product product) {
        return service.saveProduct(product);
    }

    @PostMapping("/addProducts")
    public List<Product> addProducts(@RequestBody List<Product> products) {
        return service.saveProducts(products);
    }

    @GetMapping("/products")
    public List<Product> findAllProducts() {
        return service.getProducts();
    }

    @GetMapping("/productById/{id}")
    public Product findProductById(@PathVariable int id) {
        return service.getProductById(id);
    }

    @GetMapping("/product/{name}")
    public Product findProductByName(@PathVariable String name) {
        return service.getProductByName(name);
    }

    @PutMapping("/update")
    public Product updateProduct(@RequestBody Product product) {
        return service.updateProduct(product);
    }

    @DeleteMapping("/delete/{id}")
    public String deleteProduct(@PathVariable int id) {
        return service.deleteProduct(id);
    }
}

8. Run Spring Boot Application

We’ve successfully built all the APIs for our application. Let’s now run the app and test the APIs.

Just go to the root directory of the application and type the following command to run it -

$ mvn spring-boot:run

The application will start at Spring Boot’s default tomcat port 8080.


Comments