tonykang22 / study

0 stars 0 forks source link

[JPA] 12장. 스프링 데이터 JPA #155

Open callmeaxxe opened 1 year ago

callmeaxxe commented 1 year ago

12.1 스프링 데이터 JPA 소개

12.1.1 스프링 데이터 프로젝트

image

12.2 스프링 데이터 JPA 설정

필요 라이브러리

// https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa
implementation 'org.springframework.data:spring-data-jpa:3.0.0'

// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa
implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.0.0'

"Starter for using Spring Data JPA with Hibernate".

환경설정

image

@Configuration
@EnableJpaRepositories(basePackages = "jpabook.jpashop.repository")
public class AppConfig {}

12.3 공통 인터페이스 기능

public interface JpaRepository<T, ID extends Serializable> 
                                                                    extends PagingAndSortingRepository<T, ID> {
    ...
}
public interface MemberRepository extends JpaRepository<Member, Long> {
    Member findByUsername(String username);
}

image

12.4 쿼리 메소드 기능

12.4.1 메소드 이름으로 쿼리 생성

12.4.2 JPA NamedQuery

@Entity 
@NamedQuery(
    name=”Member.findByUsername”,
    query=”select m Member m where m.username = :username”) 
public class Member {
    ...
}
public interface MemberRepository extends JpaRepository<Member, Long> {
    List<Member> findByUsername(@Param("username") String username);
}

12.4.3 @Query, 리포지토리 메소드에 쿼리 정의

public interface MemberRepository extends JpaRepository<Member, Long> {
    @Query("select m from Member where m.username = :name")
    Member findByUsername(@Param("name") String username);

    @Query(value = "SELECT * FROM MEMBER WHERE age = ?0", nativeQuery = true)
    Member findByAge(Integer age);
}

12.4.5 벌크성 수정 쿼리

@Modifying(clearAutomatically = true)
@Query("update Product p set p.price = p.price * 1.1 where p.stockAmount < :stockAmount")
int bulkPriceUp(@Param("stockAmount") String stockAmount);

12.4.7 페이징과 정렬

public interface MemberRepository extends JpaRepository<Member, Long> {
    // Page 사용. count 쿼리 호출
    Page<Member> findByNameStartingWith(String name, Pageable pageable);

    // count 쿼리 호출 안함
    List<Member> findByNameEndingWith(String name, Pageable pageable);
}
PageRequest pageRequest = new PageRequest(0, 10, new Sort(Direction.DESC, "name"));
Page<Member> result = memberRepository.findByNameStartingWith("김", pageRequest);

List<Member> members = result.getContent(); // 조회된 데이터
int totalPages = result.getTotalPages(); // 전체 페이지 수
boolean hasNextPage = result.hasNextPage(); // 다음 페이지 존재 여부

12.5 명세(Specification)

12.6 사용자 정의 리포지토리 구현

public interface MemberRepositoryCustom {
    public List<Member> findMemberCustom();
}
public interface MemberRepositoryCustomImpl implements MemberRepositoryCustom {

    @Override
    public List<Member> findMemberCustom() {
        ...
    }
}

12.7 Web 확장

12.7.1 설정

@Configuration
@EnableWebMvc
@EnableSpringDataWebSupport
public class WebAppConfig {
    ...
}

12.7.2 도메인 클래스 컨버터 기능

@Controller
public class MemberController {

    @RequsetMapping("member/memberUpdateForm")
    public String memberUpdateForm(@RequestParam("id") Member member, Model model) {
        ...
    }
}

12.7.3 페이징과 정렬 기능

GET {...}/members?page0&size=20&sort=name,desc&sort=address.city

@RequestMapping(value = "/members", method = RequestMethod.GET)
public String list(@PageableDefault(size = 12, sort = "name") Pageable pageable, ...) {
    Page<Member> page = memberService.findMembers(pageable);
    ...
}
GET {...}/members?members_page=0&order_page=1

public String list(
    @Qualifier("member") Pageable memberPageable,
    @Qualifier("order") Pageable orderPageable, ...
){...}

12.8 스프링 데이터 JPA 가 사용하는 구현체

@Repository
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
    @Transactional
    @Override
    public <S extends T> S save(S entity) {
        ...
    }
}

12.10 스프링 데이터 JPA 와 QueryDSL 통합

12.10.1 QueryDslPredicateExecutor

public interface ItemRepository 
    extends JpaRepository<Item, Long>, QueryDslPredicateExecutor<Item> {
}

12.10.2 QueryDslRepositorySupport

public interface CustomOrderRepository {
    public List<Order> search(OrderSearch orderSearch);
}
public class OrderRespositoryImpl extends QueryDslRepositorySupport
implements CustomOrderRepository {

    public OrderRepositoryImpl() {
        super(Order.class);
    }

    @Override
    public List<Order> search(OrderSearch orderSearch) {
        QOrder order = QOrder.order;
        QMember member = QMember.member;

        JPQLQuery query = from(order);

        if (StringUtils.hasText(orderSearch.getMemberName())) {
            query.leftJoin(order.member, member)
                .where(member.name.contains(orderSearch.getMemberName()));
        }

        if (orderSearch.getOrderStatus() != null) {
            query.where(order.status.eq(orderSearch.getOrderStatus()));
        }

        return query.list(order);
    }
}