일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 이클립스
- Database
- mysql
- SpringBoot
- 문자열
- Oracle
- API
- git
- JDBC
- spring
- string
- Array
- Java
- 배열
- Board
- 조건문
- jquery
- View
- rpa
- db
- Scanner
- Uipath
- MVC
- Controller
- 상속
- Eclipse
- jsp
- React
- html
- Thymeleaf
- Today
- Total
유정잉
🎀 스프링 부트 [ 게시판 만들기 ] 본문
[ CRUD 게시판 만들기 ]
• 목록 화면(번호 1) - 전체 목록을 페이징 처리해서 조회할 수 있고, 제목/내용/작성자 항목으로 검색 과 페이징 처리를 가능하게 합니다.
• 등록 화면(번호 2) - 새로운 글을 등록할 수 있고, 등록 처리 후 다시 목록 화면으로 이동하게 됩니다.
• 조회 화면(번호 3) - 목록 화면에서 특정한 글을 선택하면 자동으로 조회 화면으로 이동합니다.
조회 화면에서는 수정/삭제가 가능한 화면(번호 4)으로 버튼을 클릭해서 이동할 수 있습니다.
• 수정/삭제 화면(번호 4)- 수정 화면에서 삭제가 가능하고 삭제 후에는 목록 페이지로 이동합니다.
글을 수정하는 경우에는 다시 조회 화면(번호 2)으로 이동해서 수정된 내용을 확인할 수 있습니다.
기능 | URL | GET/POST | 기능 | Redirect URL |
목록 | /guestbook/list | GET | 목록/페이징/검색 | |
등록 | /guestbook/register | GET | 입력 화면 | |
/guestbook/register | POST | 등록 처리 | /guestbook/list | |
조회 | /guestbook/read | GET | 조회 화면 | |
수정 | /guestbook/modify | GET | 수정/삭제 기능 화면 | |
/guestbook/modify | POST | 수정 처리 | /guestbook/read | |
삭제 | /guestbook/remove | POST | 삭제 처리 | /guestbook/list |
1) controller
package org.zerock.guestbook.controller;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/guestbook")
@Log4j2
public class GuestbookController {
@GetMapping({"/","/list"})
public String list() {
log.info("list..............");
return "/guestbook/list";
}
}
2) list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<th:block th:replace="~{/layout/basic :: setContent(~{this :: content} )}">
<th:block th:fragment="content">
<h1>GuestBook List Page</h1>
</th:block>
</th:block>
3) BaseEntity -> 자동으로 처리 되는 날짜/시간 설정
@MappedSuperclass : 해당 어노테이션이 적용된 클래스는 테이블로 생성되지 않음. 실제 테이블은 BaseEntity를 상속한 엔티티의 클래스로 데이터베이스 테이블이 생성됨
@CreatedDate : JPA에서 엔티티 생성 시간 처리
@LastModifiedDate : 최종 수정 시간을 자동으로 처리. 속성으로 insertable, updateable 등 존재 updateable=false로 지정하면 해당 엔티티 객체를 데이터베이스에 반영할 때 regdate 칼럼값은 변경되지 않는다.
package org.zerock.guestbook.entity;
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.time.LocalDateTime;
@MappedSuperclass
@EntityListeners(value = { AuditingEntityListener.class })
@Getter
public class BaseEntity {
@CreatedDate
@Column(name = "regdate", updatable = false)
private LocalDateTime regDate;
@LastModifiedDate
@Column(name ="moddate")
private LocalDateTime modDate;
}
4) GuestbookApplication -> AuditingEntityListener을 활성화 시키기 위해 @EnableJpaAuditing 설정 추가
package org.zerock.guestbook;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@SpringBootApplication
@EnableJpaAuditing
public class GuestbookApplication {
public static void main(String[] args) {
SpringApplication.run(GuestbookApplication.class, args);
}
}
5) Guestbook -> BaseEntity를 상속받아 작성
package org.zerock.guestbook.entity;
import jakarta.persistence.*;
import lombok.*;
@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Guestbook extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long gno;
@Column(length = 100, nullable = false)
private String title;
@Column(length = 1500, nullable = false)
private String content;
@Column(length = 50, nullable = false)
private String writer;
}
6) 서버 실행 -> 테이블 생성 된 것 확인
7) GuestbookRepository Interface 생성 -> extends JpaRepository
package org.zerock.guestbook.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.zerock.guestbook.entity.Guestbook;
public interface GuestbookRepository extends JpaRepository<Guestbook, Long> {
}
8) 동적 쿼리 처리를 위한 Querydsl 설정
build.gradle에 buildscript 항목 추가, plugins 항목 변경, dependencies 항목에 필요한 라이브러리 추가, 기타 추가
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}
plugins {
id 'base'
id 'java'
id 'war'
id 'org.springframework.boot' version '3.3.1'
id 'io.spring.dependency-management' version '1.1.5'
}
group = 'org.zerock'
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'
implementation 'mysql:mysql-connector-java:8.0.32' // MySQL 의존성 추가 및 버전 지정
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
runtimeOnly 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
annotationProcessor(
"javax.persistence:javax.persistence-api:2.2",
"javax.annotation:javax.annotation-api:1.3.2",
"com.querydsl:querydsl-apt:${queryDslVersion}:jpa"
)
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
}
sourceSets {
main {
java {
srcDirs = ["$projectDir/src/main/java","$projectDir/build/generated"]
}
}
}
compileJava.dependsOn('clean')
tasks.named('test') {
useJUnitPlatform()
}
9) 엔티티 테스트 -> 300개의 테스트 데이터 집어 넣기
-> 생성된 데이터의 regdate(생성시간), moddate(수정시간)이 자동으로 null이 아닌 값으로 채워지는 것 확인
package org.zerock.guestbook.repository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.zerock.guestbook.entity.Guestbook;
import java.util.stream.IntStream;
@SpringBootTest
public class GuestbookRepositoryTests {
@Autowired
private GuestbookRepository guestbookRepository;
@Test
public void insertDummies() {
IntStream.rangeClosed(1,300).forEach(i -> {
Guestbook guestbook = Guestbook.builder()
.title("Title..."+i)
.content("Content..."+i)
.writer("user"+(i%10))
.build();
System.out.println(guestbookRepository.save(guestbook));
});
}
}
10) 수정 시간 테스트 -> 엔티티 글래스는 가능하면 setter 관련 기능을 만들지 않는 것이 권장 사항이지만 필요에 따라서는 수정 기능을 만들기도 한다.
Guestbook 엔티티에 수정 기능 추가 -> Test에 수정 코드 추가 -> DB에 moddate 칼럼 값 변경됐는지 확인
public void changeTitle(String title){
this.title = title;
}
public void changeContent(String content){
this.content = content;
}
@Test
public void updateTest() {
Optional<Guestbook> result = guestbookRepository.findById(300L); //존재하는 번호로 테스트
if(result.isPresent()) {
Guestbook guestbook = result.get();
guestbook.changeTitle("Changed Title ...");
guestbook.changeContent("Changed Content ...");
guestbookRepository.save(guestbook);
}
}
11) Querysl Test 작업
- 제목/내용/작성자와 같이 단 하나의 항목으로 검색하는 경우
- 제목 + 내용, 내용 + 작성자, 제목 + 작성자와 같이 2개 항목으로 검색하는 경우
- 제목 + 내용 + 작성자와 같이 3개의 항목으로 검색하는 경우
'개발자 공부 > 🎀 스프링 공부' 카테고리의 다른 글
🎀 스프링 부트 [ JPA, Repository, @Query ] (0) | 2024.07.09 |
---|---|
🎀 스프링부트 SpringBoot 파일 생성 (0) | 2024.06.18 |
🎀 스프링 레거시 흐름과 코드 예시 (0) | 2024.06.15 |
⭐️ @PostConstruct와 @PreDestroy 빈의 초기화 + 빈의 소멸 (0) | 2024.05.29 |
⭐️ Controller와 RestController의 차이점 (0) | 2024.05.29 |