본문 바로가기

SpringBoot

SpringBoot(17) - Server, JPA, DB 예제(테스트 저장, 방명록 쓰기)

728x90
반응형

1) SpringBoot

   1-1) Server, JPA, DB 예제

      1-1-1) 테스트 저장

      1-1-2) 방명록 쓰기

 

 

 

 

 

1) SpringBoot

1-1) Server, JPA, DB 예제

[web4] 안에 web4.txt 파일 생성 후 내용 아래와 같이 작성 : 이를 통해 프로젝트 한 번에 파악 및 내용 공유 가능

[web4 예제]

로그인하지 않고 글을 쓰는 게시판
비밀번호를 맞게 입력하면 삭제 가능

* 테이블 구조
create table guestbook(
	num         integer auto_increment primary key,   -- 번호. 자동생성. 기본키
	name        varchar(100) not null,                -- 이름. 필수입력. 문자열. 100byte
	password    varchar(100) not null,                -- 비밀번호. 필수입력. 문자열. 100byte
	message     text not null,                        -- 본문내용. 필수입력. 긴 문자열
	inputdate   timestamp default current_timestamp   -- 작성시간. 자동입력. 현재시간
);

 

 

[web4] 안에 build.gradle 파일 내용 아래와 같이 작성

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.3.1'
	id 'io.spring.dependency-management' version '1.1.5'
}

group = 'net.datasa'
version = '0.0.1-SNAPSHOT'

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(17)
	}
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'com.mysql:mysql-connector-j'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
	useJUnitPlatform()
}

 

 

[src/main/resources] 안에 application.properties 파일 내용 아래와 같이 작성

spring.application.name=web4

#접속 포트번호
server.port=8888
#Context Path
server.servlet.context-path=/

#Logback 사용. 전체를 대상으로 로깅 레벨 지정
#error>warn>info>debug>trace
logging.level.root=info
#특정 패키지를 대상으로 로깅 레벨 지정
logging.level.net.datasa.web3=debug

#세션의 유지 시간 (기본값은 30분 = 1800초)
#단위 : s (seconds), m (minutes), h (hours), d (days)
server.servlet.session.timeout=60m

# MySQL 데이터베이스 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=Asia/Seoul&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root

# JPA 설정
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.type.descriptor.sql=trace

spring.jackson.time-zone=Asia/Seoul

 

 

[src/main/java] - [net.datasa.web4] 안에 HomeController.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {
	@GetMapping({"", "/"})
	public String home() {
		return "home";
	}
}

 

 

[src/main/resources] - [templates] 안에 home.html 파일 생성 후 아래와 같이 작성

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>web4</title>
</head>
<body>
	<h1>[ web4 ]</h1>
	
	<p>
		<a href="test">저장 테스트</a>
	</p>
	<p>
		<a href="write">방명록 글쓰기</a>
	</p>
	
</body>
</html>

 

 

 

1-1-1) 테스트 저장

(1) [src/main/java] - [net.datasa.web4.controller] 안에 GuestBookController.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.service.GuestBookService;

@Slf4j
@RequiredArgsConstructor
@Controller
public class GuestBookController {
	
	// @RequiredArgsConstructor : Lombok 라이브러리에서 제공하는 Annotation으로,
	// 해당 Annotation이 적용된 필드를 기반으로 생성자를 자동 생성해주는 역할을 한다.
	// (객체 변수에 final 키워드를 붙여 값이 변경되지 않도록 만듦)
	// 따라서 GuestBookController 클래스는 "@RequiredArgsConstructor" Annotation을 통해
	// 생성자를 만들어 주기 때문에 아래의 service 객체 정의 코드만으로 생성자를 실행시켜 서비스 객체를 자동으로 생성해줌!
	private final GuestBookService guestbookService;
	
	/*
	 * public class GuestBookController {
	 * 	GuestBookController(GuestBookService guestbookService) {
	 * 		this.guestbookService = guestbookService;
	 * 	}
	 * }
	*/
	
	// home.html에서 "test" 경로 클릭하면 처리할 메소드 정의
	// GuestBookService의 test() 메서드 호출하여 entity 생성하여 DB에 저장
	// 실행 후 메인화면으로 다시 redirect
	@GetMapping("test")
	public String test() {
		guestbookService.test();
		return "redirect:/";
	}
	
}

 

 

(2) [src/main/java] - [net.datasa.web4] 안에 Web4Application.java 파일 생성 후 아래와 같이 "@EnableJpaAuditing" Annotation 추가

package net.datasa.web4;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class Web4Application {

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

}

 

 

(3) [src/main/java] - [net.datasa.web4.domain.entity] 안에 GuestBookEntity.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.domain.entity;

import java.time.LocalDateTime;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="guestbook")
@EntityListeners(AuditingEntityListener.class)
public class GuestBookEntity {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name="num")
	Integer num;
	
	@Column(name="name", nullable = false, length = 100)
	String name;
	
	@Column(name="password", nullable = false, length = 100)
	String password;
	
	@Column(name="message", nullable = false, columnDefinition = "text")
	String message;
	
	@CreatedDate
	@Column(name="inputdate")
	LocalDateTime inputdate;
}

 

 

(4) [src/main/java] - [net.datasa.web4.repository] 안에 GuestBookRepository.java 파일 생성 후 아래와 같이 작성

(주의 : Class가 아닌 Interface로 파일 생성한다!)

package net.datasa.web4.repository;

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

import net.datasa.web4.domain.entity.GuestBookEntity;

@Repository
public interface GuestBookRepository extends JpaRepository<GuestBookEntity, Integer> {

}

 

 

(5) [src/main/java] - [net.datasa.web4.service] 안에 GuestBookService.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.service;

import org.springframework.stereotype.Service;

import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.domain.entity.GuestBookEntity;
import net.datasa.web4.repository.GuestBookRepository;

@RequiredArgsConstructor
@Service
@Transactional
public class GuestBookService {
	
	private final GuestBookRepository guestbookRepository;

	// 저장 테스트
	public void test() {
		// GuestBookEntity entity = new GuestBookEntity(1, "aaa", "111", "글 내용1", null);
		
		GuestBookEntity entity = GuestBookEntity.builder()
				.name("aaa")
				.password("111")
				.message("글 내용1")
				.build();
		
		guestbookRepository.save(entity);
		
	}

}

 

 

(6) 결과 화면

첫 접속 화면

 

 

"저장 테스트" 문구 클릭 시 DB에 새로운 데이터 저장됨

실행 전 화면

 

실행 후 화면

 

 

 

1-1-2) 방명록 쓰기

(1) [src/main/java] - [net.datasa.web4.controller] 안에 GuestBookController.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.service.GuestBookService;

@Slf4j
@RequiredArgsConstructor
@Controller
public class GuestBookController {
	
	// @RequiredArgsConstructor : Lombok 라이브러리에서 제공하는 Annotation으로,
	// 해당 Annotation이 적용된 필드를 기반으로 생성자를 자동 생성해주는 역할을 한다.
	// (객체 변수에 final 키워드를 붙여 값이 변경되지 않도록 만듦)
	// 따라서 GuestBookController 클래스는 "@RequiredArgsConstructor" Annotation을 통해
	// 생성자를 만들어 주기 때문에 아래의 service 객체 정의 코드만으로 생성자를 실행시켜 서비스 객체를 자동으로 생성해줌!
	private final GuestBookService guestbookService;
	
	/*
	 * public class GuestBookController {
	 * 	GuestBookController(GuestBookService guestbookService) {
	 * 		this.guestbookService = guestbookService;
	 * 	}
	 * }
	*/
	
	// home.html에서 "test" 경로 클릭하면 처리할 메소드 정의
	// GuestBookService의 test() 메서드 호출하여 entity 생성하여 DB에 저장
	// 실행 후 메인화면으로 다시 redirect
	@GetMapping("test")
	public String test() {
		guestbookService.test();
		return "redirect:/";
	}
	
	// home 화면에서 "글쓰기"를 클릭하면 입력 form으로 이동
	@GetMapping("write")
	public String write() {
		return "writeForm";
	}
	
	// 입력 form에서 글쓰고 "저장" 버튼 누르면 받아서 글 저장
	@PostMapping("write")
	public String write(@ModelAttribute GuestBookDTO dto) {
		log.debug("전달된 값 : {}", dto);
		
		guestbookService.writeSave(dto);

		return "redirect:/";
	}
}

 

 

(2) [src/main/java] - [net.datasa.web4.domain.dto] 안에 GuestBookDTO.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.domain.dto;

import java.time.LocalDateTime;

import lombok.Data;

@Data
public class GuestBookDTO {
	int num;
	String name;
	String password;
	String message;
	LocalDateTime inputdate;
}

 

 

(3) [src/main/java] - [net.datasa.web4.service] 안에 GuestBookService.java 파일 생성 후 아래와 같이 작성

package net.datasa.web4.service;

import org.springframework.stereotype.Service;

import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import net.datasa.web4.domain.dto.GuestBookDTO;
import net.datasa.web4.domain.entity.GuestBookEntity;
import net.datasa.web4.repository.GuestBookRepository;

@RequiredArgsConstructor
@Service
@Transactional
public class GuestBookService {
	
	private final GuestBookRepository guestbookRepository;

	// 저장 테스트
	public void test() {
		// GuestBookEntity entity = new GuestBookEntity(1, "aaa", "111", "글 내용1", null);
		
		GuestBookEntity entity = GuestBookEntity.builder()
				.name("aaa")
				.password("111")
				.message("글 내용1")
				.build();
		
		guestbookRepository.save(entity);
		
	}

	public void writeSave(GuestBookDTO dto) {
		GuestBookEntity entity = GuestBookEntity.builder()
				.name(dto.getName())
				.password(dto.getPassword())
				.message(dto.getMessage())
				.build();
		
		guestbookRepository.save(entity);
		
	}

}

 

 

(4) [src/main/resources] - [templates] 안에 writeForm.html 파일 생성 후 아래와 같이 작성

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>방명록 글쓰기</title>
<style>
	.index {
		display: inline-block;
		margin-right: 20px;
	}
	
	textarea {
		height: 80px;
	}
</style>
<script>
	window.onload = function() {
		let nameInput = document.querySelector("#name");
		let pwInput = document.querySelector("#password");
		let messageInput = document.querySelector("#message");
		let saveBtn = document.querySelector("#saveBtn");
		
		saveBtn.addEventListener("click", function check(event) {
			
			if (
					nameInput.value.length == 0
					|| pwInput.value.length == 0
					|| messageInput.value.length == 0
				) {
				alert("이름, 비밀번호, 내용을 모두 입력하세요");
		        
		        event.preventDefault();
		        return false;
			}
			
			if (!isNaN(nameInput.value)) {
				alert("이름은 문자로 입력하세요");
		        nameInput.focus();
		        nameInput.value = null;
		        
		        event.preventDefault();
		        return false;
			}
			
			if (!isNaN(pwInput.value)) {
				alert("비밀번호는 문자로 입력하세요");
		        pwInput.focus();
		        pwInput.value = null;
		        
		        event.preventDefault();
		        return false;
			}
			
			if (!isNaN(messageInput.value)) {
				alert("내용은 문자로 입력하세요");
				messageInput.focus();
				messageInput.value = null;
				
				event.preventDefault();
				return false;
			}
			
			return true;
			
		});
	}
</script>
</head>
<body>
	<h1>[ 방명록 글쓰기 ]</h1>
	<br>
	
	<form action="write" method="post" onsubmit="return check();">
		<table>
			<tr>
				<td class="index">이름</td>
				<td>
					<input type="text" name="name" id="name">
				</td>
			</tr>
			<tr>
				<td class="index">비밀번호</td>
				<td>
					<input type="text" name="password" id="password">
				</td>
			</tr>
			<tr>
				<td class="index">내용</td>
				<td>
					<textarea name="message" id="message"></textarea>
				</td>
			</tr>
		</table>
		
		<input type="submit" value="저장" id="saveBtn">
	</form>
	
</body>
</html>

 

 

(5) 결과 화면

첫 접속 화면

 

 

"방명록 글쓰기" 문구 클릭 시 화면

 

 

"저장" 버튼 클릭 시 결과

- 이름, 비밀번호, 내용 모두 입력했는지 체크하는 JavaScript 함수 구현

- 이름, 비밀번호, 내용 각각 입력값이 문자열로 입력되었는지 체크하는 JavaScript 함수 구현