Seite wählen

Java Spring Post Request Example

Entity – Data Layer: Maps to database tables

package app.user.model;
import app.book.model.Books;
import app.authors.model.Authors;
import jakarta.persistence.; 
import lombok.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Builder
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity

public class Kunde {

@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

@Column(nullable = false, unique = true)
private String kundenname;

private String vorName;
private String Name;
@Column(unique = true)
private String email;
@Column(nullable = false)
private String password;

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private Country country;

private boolean isActive;

@Column(nullable = false)
private LocalDateTime updatedOn;

@OneToMany(fetch = FetchType.EAGER, mappedBy = "owner")
@OrderBy("createdOn DESC")
private List books = new ArrayList<>();

@OneToMany(fetch = FetchType.EAGER, mappedBy = "owner")
@OrderBy("createdOn ASC")
private List authors = new ArrayList<>();

}

In Java Spring, an entity is a class that represents a database table. It is managed by JPA (Java Persistence API) and mapped to a table in the database.

Lombok is a Java library that helps reduce boilerplate code by automatically generating common methods like getters, setters, constructors, and builders at compile time. It’s widely used in Spring Boot applications to make entity and DTO (Data Transfer Object) classes cleaner and more readable.

@Entity marks the class as a JPA entity, enabling it to be mapped to a database table, while @Builder, @Getter, @Setter, @AllArgsConstructor, and @NoArgsConstructor simplify object creation and management.

@Builder provides a convenient way to create instances using the Builder pattern, @Getter and @Setter generate accessor methods, and the constructor annotations ensure flexibility in object instantiation.

The @Id annotation marks id as the primary key, and @GeneratedValue(strategy = GenerationType.UUID) ensures that a unique UUID is automatically generated for each entity.

This configuration allows the id field to be uniquely assigned using a UUID strategy, eliminating the need for manual ID generation in a Spring Boot application.

nullable = false → Ensures the column cannot be null (a NOT NULL constraint in SQL)

unique = true → Ensures all values in this column must be unique (adds a UNIQUE constraint in SQL)

The enumeration is additional class in same package:

package app.user.model;

public enum Country {
SPAIN, PORTUGAL, GERMANY, FRANCE, POLAND, CANADA;
}

fetch = FetchType.EAGER means in this case that when you selec 1 Client you automatically select the complete list of its books

Repository – Persistance Layer: Handles database queries

In Spring Boot, the repository layer is responsible for handling database operations (CRUD: Create, Read, Update, Delete). It acts as an interface between the application and the database.

package app.user.repository;

import app.user.model.Kunde;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;
import java.util.UUID;

@Repository
public interface KundeRepository extends JpaRepository<Kunde, UUID> {

    // Optional<User> - it can return it or not if it does not exits
    Optional<User> findByKundenname(String kundenname);

    Optional<User> findByVorName(String vorName);

}

DTO – Data Transfer Object

package app.web.dto;

import app.user.model.Country;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RegisterRequest {

    @Size(min = 6, message = "Username must be at least 6 symbols")
    private String kundenname;

    @Size(min = 6, message = "Password must be at least 6 symbols")
    private String password;

    @NotNull
    private Country country;

}

@Data: Generates getters, setters, toString(), equals(), and hashCode() methods automatically. Saves time by removing the need to manually write these methods.

@Builder: Provides a builder pattern for creating objects fluently.

@AllArgsConstructor: Generates a constructor with all fields as parameters.

@NoArgsConstructor: Generates a default (empty) constructor. Useful for frameworks like Spring, JPA, and Jackson, which require a no-arg constructor.

A DTO (Data Transfer Object) is a simple Java class used to transfer data between different layers in a Spring application, such as between the controller and service layers. It helps decouple the internal entity model from the API response, improving security, performance, and maintainability by exposing only necessary fields. DTOs prevent direct exposure of database entities, reducing risks like unintended data leaks and tight coupling between layers. They can be manually mapped or automatically converted using tools like ModelMapper or MapStruct.

Service – Business Logic Layer: Contains business Logic

package app.user.service;

import app.exception.DomainException;
import app.subscription.service.SubscriptionService;
import app.user.model.User;
import app.user.model.UserRole;
import app.user.repository.UserRepository;
import app.wallet.service.WalletService;
import app.web.dto.RegisterRequest;
import app.web.dto.LoginRequest;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Slf4j  // pomaga da se logva che dadeni operacii sa izvyrsheni
@Service
public class UserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final SubscriptionService subscriptionService;
    private final WalletService walletService;

    @Autowired
    public UserService(UserRepository userRepository,
                       PasswordEncoder passwordEncoder,
                       SubscriptionService subscriptionService,
                       WalletService walletService){
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
        this.subscriptionService = subscriptionService;
        this.walletService = walletService;
    }


    public User login (LoginRequest loginRequest){

        Optional<User> optionUser
                = userRepository.findByUsername(loginRequest.getUsername());
    if (optionUser.isEmpty()){
        throw new DomainException("Username or password are incorrect!");
    }

    // ,get na edna optional promenliva vrashta tova koeto optionala pazi
    User user = optionUser.get();

    if (!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())){
        throw new DomainException("Username or password are incorrect!");
    }
// if exception is thrown the program will terminate and will not return the user
        return null;
    }


@Transactional
public User register(RegisterRequest registerRequest){

  Optional<User> userOptional
          = userRepository.findByUsername(registerRequest.getUsername());
/*
    Optional<User> userOptional2
            = userRepository.findByFirstName(registerRequest.getUsername());
*/

  if (userOptional.isPresent()){
      throw new DomainException("Username [%s] already exist.".formatted(registerRequest.getUsername()));
  }

  // tova e save-a na inputa v DB-to
    User user = userRepository.save(initilizeUser(registerRequest));

  // sazdavane na DEFAULT entities in this case - wallet + subscription

    subscriptionService.createDefaultSubscription(user);
    walletService.createWallet(user);

    log.info("Successfully create new user account for username [%s] and id [%s]"
            .formatted(user.getUsername(), user.getId()));

    return user;
}

private User initilizeUser(RegisterRequest registerRequest){

        return User.builder()
                .username(registerRequest.getUsername())
                .password(passwordEncoder.encode(registerRequest.getPassword()))
                .role(UserRole.USER)
                .isActive(true)
                .country(registerRequest.getCountry())
                .createdOn(LocalDateTime.now())
                .updatedOn(LocalDateTime.now())
                .build();

}

public List<User> getAllUsers(){
        return userRepository.findAll();
}


public User getById(UUID id){

        return userRepository.findById(id).orElseThrow(() ->
                new DomainException("User with id [%s] not found".formatted(id)));
}


}

error: Content is protected !!