토이 프로젝트/간단한 Springboot CRUD

SpringBoot + JPA + Thymeleaf + H2를 사용한 간단한 CRUD 프로젝트

코딍코딍 2022. 8. 6. 14:12

SpringBoot + JPA + Thymeleaf + H2(DB)를 사용한 간단한 CRUD 프로젝트

 

프로젝트 구조

  • controller : UserController
  • model : User
  • repository : UserRepository
  • Service : UserService, UserServiceImpl

 

프로젝트 생성

 

H2 데이터베이스 연동

application.properties

#h2 console 활성화 및 경로 설정
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

#h2 데이터베이스 설정
spring.datasource.url=jdbc:h2:tcp://localhost/~/springbootCRUD;
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect

#hibernate 설정
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.hibernate.ddl-auto=create

spring.output.ansi.enabled=always

 

C:\Users\xxx에 springbootCRUD.mv.db 생성

 

H2 데이터베이스 처음 연결 시 URL 경로

이후 URL 경로

MySql 연동

application.properties

# MySQL 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# DB Source URL
spring.datasource.url=jdbc:mysql://localhost:3306/springCRUD?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul

# DB username
spring.datasource.username=root

# DB password
spring.datasource.password=1234

# true 설정시 JPA 쿼리문 확인 가능
spring.jpa.show-sql=true

# DDL(create, alter, drop) 정의시 DB의 고유 기능을 사용할 수 있다.
spring.jpa.hibernate.ddl-auto=update

# JPA의 구현체인 Hibernate가 동작하면서 발생한 SQL의 가독성을 높여준다.
spring.jpa.properties.hibernate.format_sql=true

참고

 

깃허브 연동

참고

 

Model

User

package com.khm.springbootCRUD.model;

import lombok.Getter;
import lombok.Setter;

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

@Entity
@Getter @Setter
public class User {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    private int age;

    private String address;

    public void change(String name, int age, String address) {
        this.name=name;
        this.age=age;
        this.address=address;
    }
}

 

repository

UserRepository

package com.khm.springbootCRUD.repository;

import com.khm.springbootCRUD.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

 

Service

UserService

package com.khm.springbootCRUD.service;

import com.khm.springbootCRUD.model.User;
import com.khm.springbootCRUD.repository.UserRepository;

import java.util.List;

public interface UserService {
    void createUser(User user);
    void deleteUser(Long id);
    void updateUser(User user);
    List<User> findUsers();
    User findUser(Long id);
}

UserServiceImpl

package com.khm.springbootCRUD.service;

import com.khm.springbootCRUD.model.User;
import com.khm.springbootCRUD.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

@Service
@RequiredArgsConstructor
@Transactional
public class UserServiceImpl implements UserService{
    private final UserRepository userRepository;

    @Override
    public void createUser(User user) { //생성
        userRepository.save(user);
    }

    @Override
    public void deleteUser(Long id) { //삭제
        Optional<User> findUserOptional = userRepository.findById(id);
        User user = findUserOptional.orElseThrow(() -> new NoSuchElementException());
        userRepository.delete(user);
    }

    @Override
    public void updateUser(User user) { //수정
        Optional<User> findUserOptional = userRepository.findById(user.getId());
        if(findUserOptional.isPresent()) {
            User findUser = findUserOptional.get();
            findUser.change(user.getName(), user.getAge(), user.getAddress());
        }
    }

    @Override
    public List<User> findUsers() { //전체조회
        return userRepository.findAll();
    }

    @Override
    public User findUser(Long id) { //조회
        return userRepository.findById(id).get();
    }
}

 

Controller

UserController

package com.khm.springbootCRUD.controller;

import com.khm.springbootCRUD.model.User;
import com.khm.springbootCRUD.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.List;

@Controller
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @GetMapping("/")
    public String home() {
        return "createUser";
    }

    @PostMapping("/")
    public String createUser(@ModelAttribute User user) {
        userService.createUser(user);
        return "redirect:/";
    }

    @GetMapping("/users")
    public String users(Model model) {
        List<User> users = userService.findUsers();
        model.addAttribute("users",users);
        return "users";
    }

    @GetMapping("/user/edit/{id}")
    public String editUser(@PathVariable("id") Long id, Model model) {
        model.addAttribute("user", userService.findUser(id));
        return "editUser";
    }

    @PostMapping("/user/edit")
    public String edit(@ModelAttribute("user") User user) {
        userService.updateUser(user);
        return "redirect:/users";
    }

    @GetMapping("/user/delete/{id}")
    public String deleteUser(@PathVariable("id") Long id) {
        userService.deleteUser(id);
        return "redirect:/users";
    }
}

 

view

createUser.html

<!DOCTYPE html>
<html>
<head><title>Title</title></head>
<body>
<h2>User 생성 (Create)</h2>
<form action="/" method="post">
    <p>이름: <input type="text" name="name" placeholder="이름을 입력해주세요." size="15">
    <p>나이: <input type="text" name="age" placeholder="나이를 입력해주세요." size="15">
    <p>주소: <input type="text" name="address" placeholder="주소를 입력해주세요." size="15">
    <p><input type="submit" value="User 생성">
    <a href="/users"><input type="button" value="User 리스트 보기"></a>
</form>
</body>
</html>

editUser.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>Title</title></head>
<body>
<h2>User 수정 (Update)</h2>
<form action="/user/edit" method="post" th:object="${user}">
    <p>ID: <input type="text" th:field="*{id}" size="15" readonly>
    <p>이름: <input type="text" th:field="*{name}" size="15">
    <p>나이: <input type="text" th:field="*{age}" size="15">
    <p>주소: <input type="text" th:field="*{address}" size="15">
    <p><input type="submit" value="User 수정">
</form>
</body>
</html>

users.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>Title</title></head>
<body>
<h2>User 리스트 (Read)</h2>
    <table>
        <tr>
            <th>ID</th>
            <th>이름</th>
            <th>나이</th>
            <th>주소</th>
            <th>수정</th>
            <th>삭제</th>
        </tr>
        <div th:if="${!#lists.isEmpty(users)}">
            <tr th:each="user : ${users}">
                <td th:text="${user.id}"></td>
                <td th:text="${user.name}"></td>
                <td th:text="${user.age}"></td>
                <td th:text="${user.address}"></td>
                <td><a th:href="@{/user/edit/{userId} (userId=${user.id})}">수정</a></td>
                <td><a th:href="@{/user/delete/{userId} (userId=${user.id})}">삭제</a></td>
            </tr>
        </div>
    </table>
<hr>
<a href="/"><button>User 생성</button></a>
</body>
</html>

 

 

동작 과정

1. 생성 폼

 

2. 생성

 

3. 리스트 폼

 

4. 수정

 

5. 삭제

 

 

끝으로

Springboot와 더 친숙해지기위해 시작한 프로젝트입니다. 아직 배우고있는 단계라 미흡한 점이 많습니다. 지적해주시면 감사하겠습니다.