백엔드/Spring

[Spring] Spring Data Jpa 확장 기능

kwang2134 2024. 9. 24. 14:27
728x90
반응형
728x90

Spring Data Jpa 확장 기능

  • Spring Data Jpa는 여러 가지 확장된 기능들을 제공

사용자 정의 Repository

  • 스프링 데이터 JPA가 제공하는 인터페이스를 직접 구현하려면 구현해야 하는 기능이 너무 많음
  • 개발자가 직접 구현한 메서드를 추가하여 사용하기 위한 방법

사용 방법

  • 사용자 정의 메서드를 선언하는 인터페이스 생성
  • 사용자 정의 인터페이스를 상속받는 구현체 생성
  • 구현체 내 직접 필요한 메서드를 구현
  • JpaRepository를 상속받아 Spring Data Jpa를 사용하는 Repository 클래스에서 추가로 사용자 정의 인터페이스를 상속
  • Spring Data Jpa가 상속받은 인터페이스 이름 + Impl 조건으로 구현체를 검색해 빈으로 등록
  • 리포지토리 인터페이스 이름 + Impl 또는 사용자 정의 인터페이스 이름 + Impl 형태의 구현체를 알아서 검색 후 등록
//사용자 정의 인터페이스 정의
public interface CustomUserRepository {
    List<User> findUsersByAgeCustom(int age);
}

// 사용자 정의 인터페이스 구현체
public class CustomUserRepositoryImpl implements CustomUserRepository {
    
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    @Transactional
    public List<User> findUsersByAgeCustom(int age) {
        return entityManager.createQuery("SELECT u FROM User u WHERE u.age = :age", User.class)
                            .setParameter("age", age)
                            .getResultList();
    }
}

//Spring Data Jpa Repository 인터페이스
public interface UserRepository extends JpaRepository<User, Long>, CustomUserRepository {
		//CustomUserRepository 구현체 이름을 UserRepositoryImpl로 구현하여도 가능
}

 

Impl 대신 다른 이름을 사용하려면

  • XML 설정
    • <repositories base-package="study.datajpa.repository" repository-impl-postfix="Impl"/>
  • JavaConfig 설정
    • @EnableJpaRepositories(basePackages = "study.datajpa.repository", repositoryImplementationPostfix = "Impl")

Auditing

  • 엔티티의 생성 및 수정 시점을 자동으로 기록하는 기능
  • 일반적으로 생성자, 수정자, 생성일자, 수정일자와 같은 정보를 기록

주요 어노테이션

  • @CreatedDate: 엔티티가 생성된 시간
  • @CreatedBy: 엔티티를 생성한 유저
  • @LastModifiedDate: 마지막으로 엔티티를 수정한 시간
  • @LastModifiedBy: 마지막으로 엔티티를 수정한 유저

사용 방법

  • 메인 애플리케이션 클래스에 @EnableJpaAuditing 추가
  • 생성자 및 수정자 사용 시 AuditorAware 인터페이스를 구현하여 사용자 정보를 제공
  • 엔티티에 @EntityListeners(AuditingEntityListener.class) 어노테이션 추가 
//예시
@Entity
@EntityListeners(AuditingEntityListener.class) 
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @CreatedDate
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime lastModifiedDate;

    @CreatedBy
    private String createdBy;

    @LastModifiedBy
    private String lastModifiedBy;

}

 

@EntityListeners(AuditingEntityListener.class) 전체 적용

<!-- META-INF/orm.xml -->
<?xml version="1.0" encoding="UTF-8"?>
 <entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm 
 http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd" version="2.2">
    <persistence-unit-metadata>
        <persistence-unit-defaults>
            <entity-listeners>
                <entity-listener class="org.springframework.data.jpa.domain.support.AuditingEntityListener"/>
            </entity-listeners>
        </persistence-unit-defaults>
    </persistence-unit-metadata>
</entity-mappings>

 

Web 확장 - 도메인 클래스 컨버터

  • HTTP 파라미터로 넘어온(@PathVariable) PK 값을 통해 바로 객체로 컨버팅
  • HTTP 요청은 PK 값을 받지만 도메인 클래스 컨버터가 중간에 동작하여 해당하는 엔티티를 반환
  • 트랜잭션이 없는 범위에서 조회하여 영속성 컨텍스트의 관리를 받지 못함 -> 지연 로딩 객체에 접근할 수 없음
  • 단순 조회용 정도로만 사용 
    //도메인 클래스 컨버터 적용 X
    @GetMapping("/{id}")
    public String findUser(@PathVariable("id") Long id) {
    	User user = userRepository.findById(id).get();
        return user.getUsername();
    }

    //도메인 클래스 컨버터 적용 O
    @GetMapping("/{id}")
    public String findUser(@PathVariable("id") User user) {
        return user.getUsername();
    }

 

Web 확장 - Paging & Sorting

  • 페이징과 정렬 기능을 MVC 에서 사용 가능
  • 페이징과 정렬 조건을 파라미터로 넘겨 사용
  • @PageableDefault 어노테이션을 통해 정의하는 방법도 존재
  • 페이징 정보가 둘 이상인 경우 접두사를 통해 구분
//파라미터를 통한 페이징과 정렬
@GetMapping("/users")
public Page<User> list(Pageable pageable) {
 	Page<User> page = memberRepository.findAll(pageable);
 	return page;
}

//요청 파라미터 예시
/users?page=0&size=3&sort=id,desc&sort=username,desc

//어노테이션을 사용한 페이징과 정렬
@GetMapping("/users_page")
public String list(@PageableDefault(size = 12, sort = "username", direction = Sort.Direction.DESC) Pageable pageable) {
    
}

//페이징 정보가 둘 이상인 경우
@Qualifier("user") Pageable userPageable,
@Qualifier("group") Pageable groupPageable,

 


실전! 스프링 데이터 JPA 강의 | 김영한 - 인프런 (inflearn.com) 강의 내용 참고

728x90

'백엔드 > Spring' 카테고리의 다른 글

[Spring] Querydsl DTO & 동적 쿼리  (2) 2024.09.26
[Spring] Querydsl  (1) 2024.09.25
[Spring] 쿼리 메서드  (0) 2024.09.23
[Spring] Spring Data JPA  (2) 2024.09.22
[Spring] JPA 컬렉션 조회 최적화 & OSIV  (2) 2024.09.21