Spring Boot

250225 Spring Boot 07 - 객체지향 Entity, JPA auditing, 블로그 만들기(2)

suerte10 2025. 2. 25. 18:18

1. Post.java 파일 수정

1) 클래스에 @AllArgsConstructor 추가, access 속성의 AccessLevel을 PRIVATE으로 설정

* 빌더를 만들기 위해 추가한 것이므로 클래스 외부에서 접근할 필요는 없음

2) 클래스에 @Builder 추가

3) id 필드에 @GeneratedValue 추가, strategy 속성의 GenerationType을 IDENTITY로 설정

4) title 필드에 @Basic 추가, optional 속성을 false로 설정

* null이 되면 안되는 필드에는 추가해주는 속성

* 가능하면 테이블의 컬럼들과 필드들을 매핑해주는 것이 좋다(PK 컬럼에는 @Id, not null인 컬럼에는 @Basic 등..)

 

 

 

2. 상속을 활용한 객체지향 엔터티 설계 - @MappedSuperClass

1) 계속 반복되서 공통으로 들어가는 필드들이 있으면 부모 클래스(super class)를 만들고 상속을 시키면 편하다.

2) domain 패키지 하위에 BaseTimeEntity.java 파일 생성

 

3) Post 클래스 파일이 BaseTimeEntity를 상속하도록 수정

 

* 단위 테스트

단위 테스트 결과 콘솔에 출력되는 내용 중 일부. toString()메서드 결과에서 부모 클래스의 필드는 출력되지 않는 것을 볼 수 있다.

* 단위 테스트를 할 때는 callSuper 속성을 별도로 지정하지 않았음(이 경우 기본값은 false)

* 만약 부모 클래스의 필드도 toString() 메서드로 출력하고 싶은 경우 @ToString 애너테이션에도 callSuper = true 속성을 부여하면 된다.

 

※ callSuper

롬복에서는 equals 메서드를 만들 때, 기본적으로 갖고있는 모든 필드의 값이 같아야 같은 객체로 리턴을 해주도록 만든다.

따라서 상위 클래스가 생기면 상속받는 필드들을 어떻게 처리할 것인지 설정해줘야 한다.

* callSuper 속성의 default 값은 false

 

 

 

3. Comment.java 파일 수정

 

 

 

4. JPA auditing

※ 참고 : 애너테이션도 상속을 받는다.

@SpringBootApplication 애너테이션이 상속받는 여러 애너테이션들. 이 덕분에 기본적인 설정들이 세팅되게 된다.

 

1) 개요

 

2) BaseTimeEntity 클래스 수정

 

3) 단위 테스트

※ CrudRepository의 save() 메서드

save() 메서드의 리턴타입 S는 엔터티의 타입을 말한다.

 

단위 테스트 메서드
단위 테스트 결과 콘솔에 출력되는 내용 중 일부

* Post 엔터티의 id 필드에 generated value를 IDENTITY로 설정했기 때문에 SQL은 default를 입력하는 것으로 작성됨

* 단위 테스트 결과에서 save() 메서드 호출 후 created_time, modified_time 컬럼에 시간 정보가 자동으로 설정되고, "identity"로 설정된 id 필드 값도 자동으로 설정된 것을 볼 수 있다.

 

 

 

5. 엔터티 업데이트용 메서드 만들기

1) Post 클래스 파일 수정

 

2) 단위 테스트

테스트 메서드

 

* modifiedTime의 값으로 수정되지 않은 객체가 출력되었지만, 그것은  아규먼트로 입력한 entity를 출력했기 때문이다. save() 메서드로 리턴되는 entity를 출력해보면 modifiedTime의 값이 수정된 것을 확인할 수 있다.

 

 

 

6. delete() 메서드

 

 

 

7. 더미 데이터 생성

1) 단위 테스트 메서드를 활용해서 더미 데이터를 만들 수 있다.

단위 테스트를 실행하면 50개의 더미 데이터가 DB에 생성된다.

 

 

 

8. 메인 화면 작성

1) web 패키지 하위에 HomeController.java 파일 생성

 

2) templates 하위에 index.html 파일 생성

 

3) templates 하위에 layout 폴더 생성 ==> 폴더 하위에 fragments.html 파일 생성(springboot3 프로젝트에 있는 파일 복사 후 붙여넣기)

4) fragments.html 파일 수정

 

5) index.html 파일 수정

 

6) dto 패키지 하위에 PostListItemDto.java 파일 생성

 

7) web 패키지 하위에 PostController.java 파일 생성

 

8) service 패키지 하위에 PostService.java 파일 생성

 

※ @org.springframework.transaction.annotation.Transactional

- JPA는 테이블에서 select한 결과를 가지고 와서 메모리에 가지고 있는다.

- 메모리에 가지고 있는 엔터티 객체에 변화가 생기는 경우에는 업데이트 메서드가 호출이 된다.

- 위 예시에서는 검색해 온 데이터를 readOnly(읽기 전용)로 메모리에 가지고 있도록 속성값을 true로 설정해주었다.

- 이렇게 설정하면 의도치 않게 엔터티가 변경되는 것을 방지할 수 있다.

 

9) templates 하위에 post 폴더 생성 ==> 폴더 하위에 list.html 파일 생성

* Thymeleaf 날짜 다루는 법 참고(https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#dates)

 

※ 과제 : 새 글 작성 페이지 완성하기.

 

 

----------------------

JSP, JSTL은 아직도 java.time.LocalDate를 지원하지 않는다.(포맷팅 해주는 기능이 없음)

하지만 Thymeleaf는 temporals가 LocalDate 포맷팅 기능을 갖고 있다.

 

※ 과제하다가 개인적인 공부 : PRG 패턴에서 컨트롤러 메서드가 리턴하는 문자열에 redirect:를 써줘야하는 이유

예시

 

1. 사용하지 않으면, 서버는 클라이언트에게 새로운 요청을 보내도록 하지 않고, 단순히 특정 뷰 템플릿을 반환하게 된다.  (위의 예시에서 redirect:가 없었다면 컨택스트루트/list.html을 반환했을 것이다) 즉, 클라이언트가 페이지를 다시 요청하지 않고, 현재 요청을 처리한 후 서버에서 반환된 HTML을 렌더링 하게 된다.

 

2. 이 경우 발생할 수 있는 문제점

(1) PRG 패턴 위반 : 새로고침 시 동일한 POST 요청이 재실행될 수 있어, 중복 데이터가 삽입될 수 있다.

(2) 리다이렉트하려는 페이지에 서버에게 응답을 받아서 구현해야 하는 부분이 있다면 exception이 발생할 수 있다.

* 서버가 보낸 뷰 템플릿을 받아서 표시한 것이지 서버로 요청을 보낸게 아님!!(서버에서 응답이 오지 않는다)