[JAVA] Implement REST API with Spring Boot and JPA (domain layer)

Implementing a simple Web REST API server with Spring Boot + MySQL --Qiita

Outline Implement the domain layer according to the following design. Consider the architecture of Web API implemented by Spring Boot --Qiita

Create the following 3 classes as the domain layer.

├── domain
│   ├── object
│   │   └── User.java
│   ├── repository
│   │   └── UserRepository.java
│   └── service
│       └── UserService.java

User.java A class for expressing the concept of a user on an application. There is no particular behavior this time, just hold the necessary information. It is described briefly using Lombok.

User.java


package com.example.springapi.domain.object;

import lombok.Builder;
import lombok.Data;

/**
 *User
 */
@Data
@Builder
public class User {

    /**
     *User ID
     */
    private String id;

    /**
     *User information
     */
    private String value;
}

※ Lombok @Data The following methods are created automatically.

Like this.


package com.example.springapi.domain.object;

import lombok.Builder;

/**
 *User
 */
@Builder
public class User {

    /**
     *User ID
     */
    private String id;

    /**
     *User information
     */
    private String value;

    public String getId() {
        return this.id;
    }

    public String getValue() {
        return this.value;
    }

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

    public void setValue(String value) {
        this.value = value;
    }

    public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof User)) return false;
        final User other = (User) o;
        if (!other.canEqual((Object) this)) return false;
        final Object this$id = this.getId();
        final Object other$id = other.getId();
        if (this$id == null ? other$id != null : !this$id.equals(other$id)) return false;
        final Object this$value = this.getValue();
        final Object other$value = other.getValue();
        if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false;
        return true;
    }

    public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        final Object $id = this.getId();
        result = result * PRIME + ($id == null ? 43 : $id.hashCode());
        final Object $value = this.getValue();
        result = result * PRIME + ($value == null ? 43 : $value.hashCode());
        return result;
    }

    protected boolean canEqual(Object other) {
        return other instanceof User;
    }

    public String toString() {
        return "User(id=" + this.getId() + ", value=" + this.getValue() + ")";
    }
}

@Builder Instance creation can be described in a method chain. I like this. You can create a User instance like this.

String id;
String value;
User user = User.builder()
                .id(id)
                .value(value)
                .build();

Actually, the following code is generated by Lombok.

package com.example.springapi.domain.object;

import lombok.Data;

/**
 *User
 */
@Data
public class User {

    /**
     *User ID
     */
    private String id;

    /**
     *User information
     */
    private String value;

    @java.beans.ConstructorProperties({"id", "value"})
    User(String id, String value) {
        this.id = id;
        this.value = value;
    }

    public static UserBuilder builder() {
        return new UserBuilder();
    }

    public static class UserBuilder {
        private String id;
        private String value;

        UserBuilder() {
        }

        public UserBuilder id(String id) {
            this.id = id;
            return this;
        }

        public UserBuilder value(String value) {
            this.value = value;
            return this;
        }

        public User build() {
            return new User(id, value);
        }

        public String toString() {
            return "User.UserBuilder(id=" + this.id + ", value=" + this.value + ")";
        }
    }
}

UserRepository.java Interface between domain layer and infrastructure layer. The interface you want to use at the domain layer is defined here. This interface reverses the dependencies between the domain layer and the infrastructure layer (the principle of dependency reversal).

UserRepository.java


package com.example.springapi.domain.repository;

import com.example.springapi.domain.object.User;

import java.util.Optional;

/**
 *Interface with infrastructure layer
 */
public interface UserRepository {

    /**
     *User search
     *
     * @param id User ID you want to search
     * @return user
     */
    Optional<User> findById(String id);

    /**
     *User created and updated
     *
     * @param user User created and updated
     * @return User after update
     */
    User save(User user);

    /**
     *Delete user
     *
     * @param id User ID you want to delete
     */
    void deleteById(String id);
}

UserService.java A class that describes unnatural business logic is written in User.java. Manipulate the persisted user information using the interface defined earlier. The implementation class of UserRepository is solved by using the mechanism called DI container of Spring. (If there is no interface implementation, you will still get a compile error at this point.)

UserService.java


package com.example.springapi.domain.service;

import com.example.springapi.domain.object.User;
import com.example.springapi.domain.repository.UserRepository;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
 *User operation logic
 */
@Service
@RequiredArgsConstructor
public class UserService {

    @NonNull
    private final UserRepository userRepository;

    /**
     *User search
     *
     * @param id User ID you want to search
     * @return user
     */
    public Optional<User> findById(String id) {
        return this.userRepository.findById(id);
    }

    /**
     *User created and updated
     *
     * @param user User created and updated
     * @return User after update
     */
    public User save(User user) {
        return this.userRepository.save(user);
    }

    /**
     *Delete user
     *
     * @param id User ID you want to delete
     */
    public void deleteById(String id) {
        this.userRepository.deleteById(id);
    }
}

* DI by Spring

In Spring, DI is implemented by a mechanism called DI container.

Normal java dependencies

A.java


public class A {
    private B b = new B();
}

Class A ** depends on Class B **.

For Spring DI

In Spring, there is a mechanism called DI container that automatically injects an instance into the declared variable. By adding @Autowired, an instance is automatically created and injected.

A.java


@Compornent
public class A {
    @Autowired
    private B b;
}

B.java


@Compornent
public class B {
}

However, the granted Autowired is valid only ** when the class (A) to be injected is obtained via the DI container **. That is, if you new class A like a normal Java application, b remains null. Therefore, when using Autowired, it is necessary to register itself in the DI container. There are various ways to register in a container, but in Spring Boot, it is basically registered by assigning @Compornent to the class. The @Service used this time is an alias for @Compornent.

* Types of DI by Spring

The DI of Spring has the following notation. IntelliJ gets angry when I do field injection. (For various reasons such as reusability, invariance of instances, and explicit dependency) There is also setter injection, but I have not used it, so I will omit it.

--Field injection

@Compornent
public class A {
    @Autowired
    private B b;
}

--Constructor injection

@Compornent
public class A {
    private B b;
    
    @Autowired
    public A(B b) {
        this.b = b;
    }
}

* Constructor injection with Lombok

@Autowired can be omitted if there is only one constructor. If you use the annotation of Lombok's constructor generation, you can omit it so far.

@RequiredArgsConstructor
@Compornent
public class A {
    @NonNull
    private final B b;
}

Recommended Posts

Implement REST API with Spring Boot and JPA (domain layer)
Implement REST API with Spring Boot and JPA (Application Layer)
Implement REST API with Spring Boot and JPA (Infrastructure layer)
Implement a simple Rest API with Spring Security with Spring Boot 2.0
Implement REST API in Spring Boot
Implement a simple Rest API with Spring Security & JWT with Spring Boot 2.0
Implement a simple Web REST API server with Spring Boot + MySQL
Implement GraphQL with Spring Boot
Hello World (REST API) with Apache Camel + Spring Boot 2
Customize REST API error response with Spring Boot (Part 2)
Customize REST API error response with Spring Boot (Part 1)
Spring with Kotorin --4 REST API design
Handle Java 8 date and time API with Thymeleaf with Spring Boot
Connect to database with spring boot + spring jpa and CRUD operation
Domain Driven Development with Java and Spring Boot ~ Layers and Modules ~
[Beginner] Let's write REST API of Todo application with Spring Boot
Creating REST APIs with Spring JPA Data with REST and Lombok incredibly easy.
HTTPS with Spring Boot and Let's Encrypt
Implement CRUD with Spring Boot + Thymeleaf + MySQL
Implement paging function with Spring Boot + Thymeleaf
Implementation method for multi-data source with Spring boot (Mybatis and Spring Data JPA)
Try to implement login function with Spring Boot
Create a web api server with spring boot
Download with Spring Boot
Testing JPA entities and repositories using Spring Boot @DataJpaTest
Try using DI container with Laravel and Spring Boot
I created an api domain with Spring Framework. Part 2
Switch environment with Spring Boot application.properties and @Profile annotation
Automatically map DTOs to entities with Spring Boot API
Spring Security usage memo: Cooperation with Spring MVC and Boot
Spring Boot with Spring Security Filter settings and addictive points
A memorandum when creating a REST service with Spring Boot
I created an api domain with Spring Framework. Part 1
Introduce swagger-ui to REST API implemented in Spring Boot
Attempt to SSR Vue.js with Spring Boot and GraalJS
Connect Spring Boot and Angular type-safely with OpenAPI Generator
Generate barcode with Spring Boot
Spring Boot Introductory Guide I tried [Accessing Data with JPA]
Get started with Spring boot
Hello World with Spring Boot!
Run LIFF with Spring Boot
SNS login with Spring Boot
File upload with Spring Boot
Spring Boot starting with copy
Let's make a simple API with EC2 + RDS + Spring boot ①
Until INSERT and SELECT to Postgres with Spring boot and thymeleaf
Spring with Kotorin ―― 7. Service layer
Try hitting the zip code search API with Spring Boot
Spring Boot starting with Docker
Set cookies with Spring Boot
REST API testing with REST Assured
Use Spring JDBC with Spring Boot
With Spring boot, password is hashed and member registration & Spring security is used to implement login function.
Add module with Spring Boot
Getting Started with Spring Boot
Link API with Spring + Vue.js
Create microservices with Spring Boot
Send email with spring boot
8 things to insert into DB using Spring Boot and JPA
Let's find out how to receive in Request Body with REST API of Spring Boot
Proxy and timeout settings when calling API in Spring Rest Template