스프링데이터 + JPA/스프링 데이터 JPA 30

19. JPA 힌트, Lock

먼저 JPA 힌트란, SQL에는 Hint 라는 것이 있다. 그러니까, SELECT employee_name FROM employees USE INDEX(employee_idx) WHERE department_id = 10; Hint 라는 것은 어떤 명령을 처리하기 위해 최적화된 방법?을 지시해 주는 것이다. mysql에서는 저렇게 use index로 힌트를 주로 제공한다고 한다. use index말고도 여러 힌트들이 있다고 한다. USE INDEX : 사용할 인덱스를 지정합니다. FORCE INDEX: USE INDEX와 비슷하지만 더 강력합니다. 비용을 고려하지 않습니다. IGNORE INDEX: 최적화 프로그램에 특정 인덱스를 무시하도록 지시합니다. 여튼, sql문에 쿼리 실행 방법에 대해 뭔가 최적..

18. @EntityGraph

엔티티 그래프 연관된 엔티티들을 한번에 조회해 오는 방법. join fetch 그거임. 엔티티 그래프 이전에, 객체 그래프 라는 것이 객체간의 연결된 관계를 보여주는 그래프임. 이런 거. 엔티티도 마찬가지임. 엔티티그래프란 엔티티간의 연결된 관계를 보여주는 그래프. join fetch라는 개념이, 이런 엔티티그래프임. join fetch라는게 이런 엔티티 그래프를 다 끌고온다는 개념임. 그래서 옛날에 join fetch 배웠을 때 fetch한 건 select에다가 별칭으로 fetch한 것의 일부분만 가져오고 그런 게 안된다고 했던 거임. 그래서 여튼, 지금 사실 Spring Data JPA가 아니라 Jpa스타일로 그냥 쿼리로 했는데, @Query("select m from Member m join fet..

17. 벌크성 수정쿼리

우리가 기존 수정은 데이터를 가져온 다음, 그걸 트랜잭션 내부에서 엔티티의 값을 변경을 하면 알아서 update 쿼리가 commit 시점에 나간다. 근데, 만약 예를 들어 전체 회사원의 연봉을 10% 올리고 싶다면? 이렇게 한번에 bulk(통으로)적으로 수정하는 걸 벌크성 수정 쿼리라고 한다. 먼저 순수 JPA에서 public int bulkAgePlus(){ return em.createQuery("update Member m set m.age= m.age + 3") .executeUpdate(); } 그냥 통으로 update 시켜 버리면 됨. 조건 넣고 싶을 경우 인자로 받던지 해서 넣으면 되고, 그리고 나름 중요한 부분이, executeUpdate() 저 부분. 저걸 해야 영향받은 row의 개수를 ..

16. 스프링 데이터 JPA 페이징, 정렬

스프링 데이터 JPA에서 페이징과 정렬을 정말 간단히 지원해 준다. 스프링 데이터 JPA는 페이징과 정렬을 표준화 시켜놨다. org.springframework.data.domain.Sort 와 org.springframework.data.Pageable 이 두개로 표준화 시켜놨음. 페이징도 요새는 2가지 종류가 있는데, 추가 count 결과를 포함하는 페이징과, 추가 count 결과를 포함하지 않는, 다음 페이지가 있나 없나 확인 가능한(내부적으로 limit + 1 하나 더 조회) 왜 모바일 같은 경우 아래로 내리면 그냥 더 나오는.. org.springframework.data.Page가 총 count가 몇갠지 추가로 쿼리를 날리는 페이징이고, org.springframework.data.Slice가..

15. 순수 JPA 페이징, 정렬

지금까지 뭐 select * from member; 이런 식으로 그냥 다 데려왔었는데, 우리가 DB에 있는 걸 사실 다 끌고 올 수는 없음. 적당한 단위로 끊어서 가지고 와야 함. 그래서 게시판 보면 페이지별로 끊어놓는 거임. 조건 나이가 10살 이름으로 내림차순 첫번째 페이지. 페이지당 보여줄 데이터는 3건 public List findByPage(int age, int offset, int limit){ return em.createQuery("select m from Member m where m.age = :age order by m.username desc", Member.class) .setParameter("age", age) .setFirstResult(offset) .setMaxResul..

14. 스프링 데이터 JPA 반환 타입

스프링 데이터 JPA는 이 조회해는 것의 반환타입을 유연하게 제공함. 컬렉션으로, 아니면 단건, 아니면 단건인데 Optional로 등등.. List findListByUsername(String username); Member findMemberByUsername(String username); Optional findOptionalByUsername(String username); 굉장히 많은 반환타입이 보장된다. 컬렉션, 단건, 옵셔널 이거 외에도 많다. 컬렉션은 없으면 그냥 빈 컬렉션. 단건은 null. 이게 조금 순수 JPA와 다른 부분인데 순수 JPA는 없으면 예외를 날리는 데 스프링 데이터 JPA는 그 예외를 잡아서 null로 return함. 옵셔널은 마치 양자처럼 있거나 없거나. 이 외에도 ..

13. 파라미터 바인딩

파라미터 바인딩은 위치기반이 있고 이름기반이 있음 select m from Member m where m.username = ?0 select m from Member m where m.usernmae = :name 위치기반은 사용하지 않는다고 함. 확실히 이름기반이 훨씬 명확함. @Query("select m from Member m where m.username = :username and m.age = :age") List findUser(@Param("username") String username, @Param("age") int age); 이렇게 바인딩 했었음. @Param(SQL상파라미터명) 타입 인자이름 여튼 이런거는 지금까지 많이 해왔던 거고, 컬렉션을 인자로 넣을 수 있는데 이게 무슨 ..

12. Dto나 테이블 중 특정 값만 조회해 오기

지금까지 그냥 엔티티 전체를 가지고 왔음. 이번엔 스프링 데이터 JPA로 Dto나 특정 값만 가져오는 걸 해 볼텐데, 이거는 메소드명으로 쿼리 자동생성으로는 못한다. 저 익명@Query를 써야 한다. @Query("select m.username from Member m") List findUsernames(); 그냥 우리가 순수 JPA에서 jpql 짜듯이 하면 된다. 그럼 다음은 Dto @Data public class MemberDto { private Long id; private String username; private String teamName; public MemberDto(Long id, String username, String teamName) { this.id = id; this...

11. @Query, 메소드에 쿼리 정의

그냥 @Query("select m from Member m where m.username = :username and m.age = :age") List findUser(@Param("username") String username, @Param("age") int age); 이렇게 곧바로 쓰는거다. 이거는 네임드쿼리를 곧바로 쓰는거라고 보면 된다. @Query("select m from Member m where m.username = :username and m.age = :age") List findUser(@Param("username") String username, @Param("age") int age); @Query("쿼리와 :파라미터") List 메소드명(@Param("쿼리상파라미터명"..

10. JPA 네임드 쿼리

얘는 실무에서 거의 쓸 일이 없음. 네임드 쿼리는 쿼리에 이름을 부여하고 호출하는 기능 이거보다 더 상위호환이 될 수 있는 좋은 기능이 있기에 이거는 잘 안씀. 그래도 소개를 해 보자면, 사용하려면 @NamedQuery( name = "Member.findByUsername", query="select m from Member m where m.username=:username" ) public class Member { ... 이렇게 엔티티에 적어놓음( 따로 xml파일에 정의해 놓을 수도 있음. ) public List findByUsernameNameQuery(String username){ return em.createNamedQuery("Member.findByUsername",Member.cla..