TIL 2023/11/07 Spring JPA Transaction

YEONGDO·2023년 11월 7일

1. SpringBoot의 JPA

1) SpringBoot 환경에서의 JPA

-SpringBoot 환경에서는 EntityManagerFactory와 EntityManager를 자동으로 생성

  • application.properties에 DB 정보를 전달해 주면 이를 토대로 EntityManagerFactory가 생성
  • @PersistenceConext 애너테이션을 사용하면 자동으로 생성된 EntityManager를 주입받아 사용할 수 있다.

2) Spring의 트랜잭션

Spring 프레임워크에서는 DB의 트랜잭션 개념을 애플리케이션에 적용할 수 있도록 트랜잭션 관리자를 제공

@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
						...
			
		@Transactional
		@Override
		public <S extends T> S save(S entity) {
		
			Assert.notNull(entity, "Entity must not be null");
		
			if (entityInformation.isNew(entity)) {
				em.persist(entity);
				return entity;
			} else {
				return em.merge(entity);
			}
		}

						...
}

예시 코드 처럼 @Transactional 애너테이션을 클래스나 메서드에 추가하면 쉽게 트랜잭션 개념을 적용할 수 있다.

  • 메서드가 호출되면, 해당 메서드 내에서 수행되는 모든 DB 연산 내용은 하나의 트랜잭션으로 묶인다.
  • 이때, 해당 메서드가 정상적으로 수행되면 트랜잭션을 커밋하고, 예외가 발생하면 롤백
  • 클래스에 선언한 @Transactional은 해당 클래스 내부의 모든 메서드에 트랜잭션 기능을 부여
  • 이때, save 메서드는 @Transactional 애너테이션이 추가되어있기 때문에 readOnly = true 옵션인 @Transactional을 덮어쓰게 되어 readOnly = false 옵션으로 적용된다.

3) 영속성 컨텍스트와 트랜잭션의 생명주기

  • 스프링 컨테이너 환경에서는 영속성 컨텍스트와 트랜잭션의 생명주기가 일치
  • 쉽게 설명하자면 트랜잭션이 유지되는 동안은 영속성 컨텍스트도 계속 유지가 되기 때문에 영속성 컨텍스트의 기능을 사용할 수 있다.

2. Spring Data JPA

  • Spring Data JPAJPA를 쉽게 사용할 수 있게 만들어놓은 하나의 모듈
  • JPA를 추상화시킨 Repository 인터페이스를 제공
  • Repository 인터페이스Hibernate와 같은 JPA구현체를 사용해서 ****구현한 클래스를 통해 사용된다.
  • 개발자들은 Repository 인터페이스를 통해 JPA를 간편하게 사용할 수 있게 되었다.

1) Spring Data JPA의 SimpleJpaRepository

  • Spring Data JPA에서는 JpaRepository 인터페이스를 구현하는 클래스를 자동으로 생성해준다.
  • Spring 서버가 뜰 때 JpaRepository 인터페이스를 상속받은 인터페이스가 자동으로 스캔이 되면, 해당 인터페이스의 정보를 토대로 자동으로 SimpleJpaRepository 클래스를 생성해 주고, 이 클래스를 Spring ‘Bean’으로 등록
  • 따라서 인터페이스의 구현 클래스를 직접 작성하지 않아도 JpaRepository 인터페이스를 통해 JPA의 기능을 사용할 수 있

3. JPA Auditing 적용

1) Timestamped

데이터의 생성(created_at), 수정(modified_at) 시간은 포스팅, 게시글, 댓글 등 다양한 데이터에 매우 자주 활용된다. 각각의 Entity의 생성 수정 시간을 매번 작성하는건 너무 비효율적이다.

  • Spring Data JPA에서는 시간에 대해서 자동으로 값을 넣어주는 기능인 JPA Auditing을 제공하고 있다.
  • @MappedSuperclass
    • JPA Entity 클래스들이 해당 추상 클래스를 상속할 경우 createdAt, modifiedAt 처럼 추상 클래스에 선언한 멤버변수를 컬럼으로 인식할 수 있다.
  • @EntityListeners(AuditingEntityListener.class)
    • 해당 클래스에 Auditing 기능을 포함시켜 준다.
  • @CreatedDate
    • Entity 객체가 생성되어 저장될 때 시간이 자동으로 저장된다.
    • 최초 생성 시간이 저장되고 그 이후에는 수정되면 안되기 때문에 updatable = false 옵션을 추가
  • @LastModifiedDate
    • 조회한 Entity 객체의 값을 변경할 때 변경된 시간이 자동으로 저장
    • 처음 생성 시간이 저장된 이후 변경이 일어날 때마다 해당 변경시간으로 업데이트된다.
  • @Temporal
    • 날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용
    • DB에는 Date(날짜), Time(시간), Timestamp(날짜와 시간)라는 세 가지 타입이 별도로 존재

4. Query Methods

Spring Data JPA에서는 메서드 이름으로 SQL을 생성할 수 있는 Query Methods 기능을 제공

  • JpaRepository 인터페이스에서 해당 인터페이스와 매핑되어있는 테이블에 요청하고자하는 SQL을 메서드 이름을 사용하여 선언할 수 있다.
  • SimpleJpaRepository 클래스가 생성될 때 위처럼 직접 선언한 JpaRepository 인터페이스의 모든 메서드를 자동으로 구현해준다.
  • JpaRepository 인터페이스의 메서드 즉, Query Methods는 개발자가 이미 정의 되어있는 규칙에 맞게 메서드를 선언하면 해당 메서드 이름을 분석하여 SimpleJpaRepository에서 구현이 된다.
  • 따라서 우리는 인터페이스에 필요한 SQL에 해당하는 메서드 이름 패턴으로 메서드를 선언 하기만 하면 따로 구현하지 않아도 사용할 수 있다.
  • findAllByOrderByModifiedAtDesc 해당 메서드 이름은 Memo 테이블에서 ModifiedAt 즉, 수정 시간을 기준으로 전체 데이터를 내림차순으로 가져오는 SQL을 실행하는 메서드를 생성할 수 있다.
  • List<Memo> findAllByUsername(String username);
    • 이렇게 Query Method를 선언했을 경우 ByUsername 에 값을 전달해줘야하기 때문에 파라미터에 해당 값의 타입과 변수명을 선언해준다.
    • 즉, Query Methods 는 메서드의 파라미터를 통해 SQL에 필요한 값을 동적으로 받아 처리할 수 있다.

마치며..

오늘은 JPA부분 정리하면서 강의를 들었다. 또 팀과제 튜터님의 피드백 링크가 올라와서 어떤 부분이 부족했고, 어떤 부분을 수정해야하는 지 확인했다. (과거) 팀장님이 순식간에 수정을 해주셨다.. 역시... 내일부터는 Spring 숙련을 들으면서 스프링지식을 쌓을거다~!

profile
개발 블로그

0개의 댓글