본문 바로가기
spring

3장 - 스프링 부트에서 JPA로 데이터베이스 다뤄보자

by kdozlo 2023. 4. 17.

Entity 클래스에서 Setter 메소드 절대 만들면 안된다.

그 대신 해당 필드 값 변경을 위해서 명확히 목적과 의도를 나타 낼 수 있는 메소드를 추가한다. 이렇게 하면, 해당 클래스의 인스턴스 값들이 언제 어디서 변해야 하는지 알 수 있고, 나중에 기능 변경 시에도 덜 복잡해진다.

 

<목적을 명확히 알 수 있는 메소드 예시>

public class Car {
	public void speedUp() {
    		this.speed += 1;
	}
}

public void 자동차_속도올리기() {
	Car.speedUp();
}

 

Setter를 대신해서 값을 만들어서 DB에 삽입하는 방법

생성자나 @Builder를 통해 최종값을 채운 후, DB에 insert 한다. 

생성자보다 @Builder를 사용했을때의 장점은 채워야 할 필드가 무엇인지 명확히 지정할 수 있다는 것이다.

 

<@Builder(빌더 패턴)를 통한 DB insert 예시>

Car.builder()
    .speed(10)
    .build();

 

Junit5에서는 @RunWith(SpringRunner.class)가 안된다.

대신, @ExtendWith(SpringExtension.class)로 변경되었다. 하지만 @SpringBootTest 사용시 생략 가능 하다.

< @SpringBootTest 사용시, @ExtendWith(SpringExtension.class) 생략 가능한 이유>

JPA에서 save의 기능

테이블에 insert/update 쿼리를 실행함

id값이 있다면 update, 없다면 insert

 

JPA에 의해 실행된 쿼리문 보는법

application.properites에

    spring.jpa.show_sql=true

를 작성한다.

 

Spring Web 계층

Web Layer

  뷰 템블릿 영역(@Controller, JSP/Freemarker)

  외부 요청과 응답에 대한 전반적인 영역(@Filter, @ControllerAdvice)

 

Service Layer

  @Service

  Controller와 Dao 중간 영역

  @Transactional이 사용되는 영역

  ※ 오해하는 부분

    - 트랜잭션, 도메인 간 순서 보장 역할만 한다.

    - 비즈니스 로직 처리 역할을 하는게 아님! => 비즈니스 처리 담당은 Domain 영역에서 한다!

 

Repository Layer

  디비 접근 영역

  Dao(Data Access Object) 영역

 

Dtos

  Dto(Data Transfer Object) - 계층간 데이터 교환을 위한 객체

 

Domain Model

  @Entity가 사용된 영역

  VO(value object) 

  무조건 데이터베이스의 테이블과 관계가 있어야 하는것은 아님(ex. VO)

 

스프링에서 Bean 주입 방법

  1. @AutoWired(이건 권장 안함 - 순환참조 발생할수 있음) 

  2. setter

  3. 생성자

 

생성자로 주입 받는 방식 권장

  @RequriedArgsConstructor( = final이 선언된 모든 필드를 인자값으로 하는 생성자 생성해줌, 롬복 어노테이션) 사용하기

   ==> 해당 클래스 의존성 관계가 변경되도 생성자 코드 수정 안해도 돼서 편함

 

Entity와 DTO(Request/Response) 분리는 필수다.

  Entity 변경은 여러 클래스에 영향을 미치므로, 자주 변경이 필요한 View 클래스는 Request/Response  DTO를 통해 변경하여 분리한다. 

 

Jpa 영속성 컨텍스트

@Transactional
public Long update(Long id, PostsUpdateRequestDto requestDto) {
    Posts posts = postsRepository.findById(id)
            .orElseThrow(() -> new
                    IllegalArgumentException("해당 게시글이 없습니다. id=" + id));

    posts.update(requestDto.getTitle(), requestDto.getContent());

    return id;
}

위 코드를 보면 update부분에서 repository에 update하는 쿼리문을 볼수 없다. 하지만 디비의 엔티티는 업데이트가 된다. 이게 가능한 이유가 바로 Jpa 영속성 컨텍스트 때문이다. 

 

영속성 컨텍스트

 - 엔티티를 영구 저장하는 환경

 

Jpa의 엔티티 매니저가 활성화된 상태로 트랜잭션 안에서 디비 데이터를 가져오면(위의 코드에서 findById로 가져옴), 영속성 컨텍스트가 유지된 상태인거다.

 

더티 체킹 이란

 - 이 상태에서 데이터 값 변경 시, 트랜잭션 끝나는 시점에 update 반연된다.

 

JPA Auditing으로 생성시간/수정 시간 자동화 가능

  - @MappedSuperclass : JPA Entity 클래스들이 BaseTimeEntity를 상속할 경우 필드들도 칼럼으로 인식가능하게 함

  - @EntityListeners(AuditingEntityListener.class) : BaseTimeEntity 클래스에 Auditing 기능 포함 시킴

  - @CreatedDate : 엔티티 생성시 시간 자동 저장

  - @LastModifiedDate : 엔티티 값 변경시 시간 자동 저장

  - @EnableJpaAuditing : JPA Auditing 활성화 시킴

 

책을 통한 구현 코드 

https://github.com/kdozlo/post-webservice

 

GitHub - kdozlo/post-webservice: "스프링 부트와 AWS로 혼자 구현하는 웹 서비스" 책을 통해 게시판 기능,

"스프링 부트와 AWS로 혼자 구현하는 웹 서비스" 책을 통해 게시판 기능, 회원 기능, 아마존 ASW 공부 - GitHub - kdozlo/post-webservice: "스프링 부트와 AWS로 혼자 구현하는 웹 서비스" 책을 통해 게시판 기

github.com

 

참고 자료

https://velog.io/@langoustine/setter%EB%A5%BC-%EC%93%B0%EC%A7%80%EB%A7%90%EB%9D%BC%EA%B3%A0

 

왜 Entity에 setter를 사용하지 말아야 할까?

Entity를 작성할 경우 작성한 필드를 setter로 작성하는 경우가 많다. setter를 사용하면 해당 Entity의 값을 변경할 수 있기 때문에 객체의 일관성을 보장할 수 없다고 알고 있기에 당연하게 Entity에서

velog.io

https://ssons.tistory.com/63

 

@RunWith(SpringRunner.class) 이란??

단위테스트 코드를 작성하던중 Junit4에서 사용하는 @RunWith(SpringRunner.class)라는 어노테이션을 지속적으로 사용해주었는데 몇 가지 의문점이 생겨서 정리하고자 합니다. 의문점은 아래와 같습니다

ssons.tistory.com

https://twer.tistory.com/entry/JUnit5-RunWith

 

[JUnit5] RunWith

스프링 프로젝트 테스트를 진행하다보면 RunWith(SpringRunner.class)를 테스트 클래스에 설정해주는 모습을 볼 수 있습니다. 하지만, 현재 JUnit5를 사용하고 있다면 RunWith를 할 수 없을 것입니다. 그 이

twer.tistory.com

https://medium.com/sjk5766/vo-value-object-%EC%A0%95%EB%A6%AC-63c207aa39f6

 

VO (Value Object) 정리

인터넷에 VO를 정리한 많은 글이 있지만 굳이 포스팅을 하는 이유는 최근 받은 리뷰 과정에서 VO를 제대로 몰랐기에 정리하고자 합니다.

medium.com

https://velog.io/@livenow/Java-VOValue-Object%EB%9E%80

 

[Java] VO(Value Object)란?

개발을 하다 자주 VO라는 개념을 들은적이 있습니다. 대략적으로 값 객체 패턴(Value object pattern) 즉, 객체를 값처럼 쓸 수 있고, 제약사항 중 하나는 객체의 인스턴스 변수가 생성자를 통해서 일단

velog.io

https://sanghoonly.tistory.com/m/101

 

@Autowired 를 가급적 쓰지 말라는 이유

@Autowired 는 생성자 주입 방식 시에도, 필드 주입 방식 시에도 사용할 수 있음. 따라서 @Autowired 를 가급적 쓰지 말라는 이유는 두 가지로 분류할 수 있음. (생성자 주입, 필드 주입 둘 다 포함)@Autowi

sanghoonly.tistory.com

https://jojoldu.tistory.com/415

 

더티 체킹 (Dirty Checking)이란?

Spring Data Jpa와 같은 ORM 구현체를 사용하다보면 더티 체킹이란 단어를 종종 듣게 됩니다. 더티 체킹이란 단어를 처음 듣는분들을 몇번 만나게 되어 이번 시간엔 더티 체킹이 무엇인지 알아보겠습

jojoldu.tistory.com