각진 세상에 둥근 춤을 추자

[Spring Boot] JPA 사용 - 간단 회원 정보 입력, 목록, 수정, 삭제 본문

Spring

[Spring Boot] JPA 사용 - 간단 회원 정보 입력, 목록, 수정, 삭제

circle.j 2023. 1. 11. 23:38

이전 글

[Spring Boot] 스프링부트 DB 연동 + Lombok 설치 +간단 회원 정보 입력, 목록, 수정

 

[Spring Boot] 스프링부트 DB 연동 + Lombok 설치 +간단 회원 정보 입력, 목록, 수정

스프링부트와 DB 연동하기 Thymeleaf Plugin for Eclipse 3.0.1 설치 [Help] - [Eclipse MarketPlace] Lombok 설치하기 https://projectlombok.org/download Download projectlombok.org Specify location 클릭 SpringToolSuite4.app - Contents - Eclipse

this-circle-jeong.tistory.com

 


JPA

 

  • JPA(Java Persistence API)는 자바 ORM 기술에 대한 API 표준으로 Java를 이용해서 데이터를 유지관리(Data Access) 할 수 있는 기술
  • Spring에서는 JPA를 쉽게 사용할 수 있도록 Spring Data JPA 라이브러리를 지원
  • JPA는 특정 DBMS에 종속되지 않고, 객체지향적인 설계로 좀 더 직관적이고 비즈니스 로직에 집중
  • JPA는 복잡한 SQL 실행이 어렵다는것과 JPA를 애플리케이션 개발에 제대로 활용하기 위해서는 많은 경험과 학습을 요구

 

 

 


JPA 주요 컴포넌트

 

 

 


JPA Entity와 Entity Manager

 

  • Entity는 Database Table에 대응하는 Java 클래스
  • Java 클래스에 @Entity 선언으로 Entity 객체 생성
  • Entity Manager는 영속성 컨텍스트(Persistence Context)에서 여러 Entity를 관리하는 객체
  • 영속성 컨텍스트는 Entity를 1차 Cache 에 저장하고 Entity Manager를 통해 접근제어

 

 

 


1. 프로젝트 생성하기

New - Spring Starter Project

 

 

  • Name: 프로젝트명
  • Type: Gradle - Groovy
  • Packaging: Jar
  • Java Version: 11
  • Language: Java
  • Group, Package: kr.co.패키지명

 

  • Spring Boot Version: 2.7.7
  • Selected: Lombok, MyBatis FrameWork, MySQL Driver, Spring Boot DevTools, Spring Web, Spring Data JPA, Thymeleaf

 

 


2. application.properties

 

프로젝트 - src/main/resources - application.properties

server.servlet.context-path=/Ch07
server.port=8080
spring.thymeleaf.cache=false

# Mybatis 설정 (DB 연동)
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/java2db
spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#MyBatis Mapper 경로설정
mybatis.mapper-locations=classpath:mappers/**/*.xml

#JPA 설정 (개발 시 console 확인)
spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto=update
logging.level.org.hibernate.type.descriptor.sql=trace

 

 


3. Ch07Application.java

 

프로젝트 - src/main/java - kr.co.ch07 (프로젝트 생성 시 패키지명) - Ch07Application.java (프로젝트명+Application.java)

@MapperScan("kr.co.ch07.dao")
package kr.co.ch07;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("kr.co.ch07.dao")
@SpringBootApplication
public class Ch07Application {

	public static void main(String[] args) {
		SpringApplication.run(Ch07Application.class, args);
	}

}

 

 


4. 정적 페이지 생성

 

프로젝트 - src/main/resources - templates - index.html 생성

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta charset="UTF-8">
		<title>Index</title>
	</head>
	<body>
		<h1>JPA 실습하기</h1>
		
		<h4>JPA 기본 메소드 실습하기</h4>	
		<a th:href="@{/user1/list}">User1 목록</a>
		
	</body>
</html>

 

프로젝트 - src/main/resources - templates - user1 (폴더) 생성 - list.html, register.html, modify.html 생성

[list.html]

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta charset="UTF-8">
		<title>user1::list</title>
	</head>
<body>
	<h3>user1 목록</h3>
	<a th:href="@{/}">User 메인</a>
	<a th:href="@{/user1/register}">user1 등록</a>
	
	<table border="1">
		<tr>
			<td>아이디</td>
			<td>이름</td>
			<td>휴대폰</td>
			<td>나이</td>
			<td>관리</td>
		</tr>
		<tr th:each="user:${users}">
			<td>[[${user.uid}]]</td>
			<td>[[${user.name}]]</td>
			<td>[[${user.hp}]]</td>
			<td>[[${user.age}]]</td>
			<td>
				<a th:href="@{/user1/modify(uid = ${user.uid})}">수정</a>
				<a th:href="@{/user1/delete(uid = ${user.uid})}">삭제</a>
			</td>
		</tr>
	</table>
</body>
</html>

 

[register.html]

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta charset="UTF-8">
		<title>user1::register</title>
	</head>
<body>
	<h3>user1 등록</h3>
	<a th:href="@{/}">User 메인</a>
	<a th:href="@{/user1/list}">user1 목록</a>
	
	<form action="/Ch07/user1/register" method="post">
		<table border="1">
			<tr>
				<td>아이디</td>
				<td><input type="text" name="uid"></td>
			</tr>
			<tr>
				<td>이름</td>
				<td><input type="text" name="name"></td>
			</tr>
			<tr>
				<td>휴대폰</td>
				<td><input type="text" name="hp"></td>
			</tr>
			<tr>
				<td>나이</td>
				<td><input type="number" name="age"></td>
			</tr>
			<tr>
				<td colspan="2" align="right"><input type="submit" value="등록"></td>
				
			</tr>
		</table>	
	</form>
	
</body>
</html>

 

[modify.html]

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta charset="UTF-8">
		<title>user1::modify</title>
	</head>
<body>
	<h3>user1 수정</h3>
	<a th:href="@{/}">User 메인</a>
	<a th:href="@{/user1/list}">user1 목록</a>
	
	<form action="/Ch07/user1/modify" method="post">
		<table border="1">
			<tr>
				<td>아이디</td>
				<td><input type="text" name="uid" th:value="${user.uid}" readonly="readonly"></td>
			</tr>
			<tr>
				<td>이름</td>
				<td><input type="text" name="name" th:value="${user.name}" ></td>
			</tr>
			<tr>
				<td>휴대폰</td>
				<td><input type="text" name="hp" th:value="${user.hp}" ></td>
			</tr>
			<tr>
				<td>나이</td>
				<td><input type="number" name="age" th:value="${user.age}" ></td>
			</tr>
			<tr>
				<td colspan="2" align="right"><input type="submit" value="수정"></td>
				
			</tr>
		</table>	
	</form>
	
</body>
</html>

 

 


5. mapper

 

프로젝트 - src/main/resources - mappers 폴더 생성 - user1.xml 생성

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.co.ch07.dao.User1DAO">
	<insert id="insertUser1">
		INSERT INTO `user1` VALUES (#{uid}, #{name}, #{hp}, #{age});
	</insert>
	<select id="selectUser1" resultType="kr.co.ch07.vo.User1VO">
		select * from `user1` where `uid`=#{uid};
	</select>
	<select id="selectUser1s" resultType="kr.co.ch07.vo.User1VO">
		select * from `user1`;
	</select>
	<update id="updateUser1">
		update `user1` set
			`name`=#{name},
			`hp`=#{hp},
			`age`=#{age}
		where
			`uid`=#{uid};		
	</update>
	<delete id="deleteUser1">
		delete from `user1` where `uid`=#{uid};
	</delete>
</mapper>

 

 

 


6. VO (Entity 클래스)

 

프로젝트 - src/main/java - kr.co.user - vo 패키지 생성 - User1VO.java 생성

package kr.co.ch07.vo;

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

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
@Table(name="user1")
public class User1VO {
	
	@Id
	private String uid;
	private String name;
	private String hp;
	private int age;
}

@Id 어노테이션을 사용하여 uid(user Id) 칼럼을 기본키(PK)로 지정한다.

 

만약, AUTO_INCREMENT 기능을 적용해야 하는 칼럼이 있다면 아래와 같이 @GeneratedValue 어노테이션을 사용한다.

@GeneratedValue(strategy = GenerationType.IDENTITY)
private int seq;

GenerationType.IDENTITY는 기본 키 생성을 데이터베이스에 위임하는 방식이다.

 

 


7. DAO

 

프로젝트 - src/main/java - kr.co.user - dao 패키지 생성 - User1DAO.java 생성

package kr.co.ch07.dao;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import kr.co.ch07.vo.User1VO;

@Mapper
@Repository
public interface User1DAO {

	public void insertUser1(User1VO vo);
	public User1VO selectUser1(String uid);
	public List<User1VO> selectUser1s();
	public void updateUser1(User1VO vo);
	public void deleteUser1(String uid);
	
}

 

 


8. Repository

 

프로젝트 - src/main/java - kr.co.user - repository 패키지 생성 - User1Repo.java 생성

package kr.co.ch07.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import kr.co.ch07.vo.User1VO;

@Repository
public interface User1Repo extends JpaRepository<User1VO, String>{
	
	
}

 

 


9. Service

 

프로젝트 - src/main/java - kr.co.user - service 패키지 생성 - User1Service.java 생성

package kr.co.ch07.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import kr.co.ch07.dao.User1DAO;
import kr.co.ch07.repository.User1Repo;
import kr.co.ch07.vo.User1VO;


@Service
public class User1Service {
	@Autowired
	private User1DAO dao;

	@Autowired
	private User1Repo repo;
	
	public void insertUser1(User1VO vo) {
		// MyBatis
		//dao.insertUser1(vo);
		
		// JPA
		repo.save(vo);
		
	}
	public User1VO selectUser1(String uid) {
		// MyBatis
		//User1VO user = dao.selectUser1(uid);
		
		// JPA
		User1VO user = repo.findById(uid).get();
		return user;
	}
	public List<User1VO> selectUser1s() {
		// MyBatis
		//List<User1VO> users = dao.selectUser1s();
		
		// JPA
		List<User1VO> users = repo.findAll();
		return users;
	}
	public void updateUser1(User1VO vo) {
		// MyBatis
		//dao.updateUser1(vo);
		
		// JPA
		repo.save(vo);
	}
	public void deleteUser1(String uid) {
		// MyBatis
		//dao.deleteUser1(uid);
		
		// JPA
		repo.deleteById(uid);
	}
}

 


10. Controller

 

프로젝트 - src/main/java - kr.co.user - controller 패키지 생성 - MainController.java 생성

package kr.co.ch07.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import kr.co.ch07.repository.User1Repo;
import kr.co.ch07.vo.User1VO;

@Controller
public class MainController {
	
	@Autowired
	private User1Repo repo;

	@GetMapping(value = {"/", "/index"})
	public String index() {
		return "/index";
	}
	
}

 

프로젝트 - src/main/java - kr.co.user - controller 패키지  - User1Controller.java 생성

package kr.co.ch07.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import kr.co.ch07.service.User1Service;
import kr.co.ch07.vo.User1VO;


@Controller
public class User1Controller {

	@Autowired
	private User1Service service;
	
	@GetMapping("/user1/list")
	public String list(Model model) {
		List<User1VO> users = service.selectUser1s();
		model.addAttribute("users", users);
		return "/user1/list";
	}
	
	@GetMapping("/user1/register")
	public String register() {
		return "/user1/register";
	}
	
	@PostMapping("/user1/register")
	public String register(User1VO vo) {
		service.insertUser1(vo);
		return "redirect:/user1/list";
	}
	
	@GetMapping("/user1/modify")
	public String modify(String uid, Model model) {
		User1VO user = service.selectUser1(uid);
		model.addAttribute("user", user);
		return "/user1/modify";
	}
	@PostMapping("/user1/modify")
	public String modify(User1VO vo) {
		service.updateUser1(vo);
		return "redirect:/user1/list";
	}
	
	@GetMapping("/user1/delete")
	public String delete(String uid) {
		service.deleteUser1(uid);
		return "redirect:/user1/list";
	}
	
}

 

 


11. 실행

 

http://localhost:8080/Ch07/

 

http://localhost:8080/Ch07/user1/list

 

http://localhost:8080/Ch07/user1/register

 

http://localhost:8080/Ch07/user1/modify

 

delete (list에서 삭제 버튼 클릭 시)