UserJPARepository_Test 해보기

coding S's avatar
Mar 20, 2024
UserJPARepository_Test 해보기

[ UserJPARepository 클래스 생성 ]

notion image
💡
JPA는 약어라 모두 대문자로 적어준다
notion image
💡
인터페이스는 인터페이스를 extends 해야 한다. (문법) 인터페이스는 다중 상속이 가능하다! 즉, 한 인터페이스는 여러 인터페이스를 extends를 사용하여 확장할 수 있다.

JpaRepository 개념 간단하게 보러가기

 

[ 리팩토링 하자! 그런데 그 전에 테스트 해보기! ]

notion image

[ UserJPARepositoryTest ]

notion image
JPA를 사용할 때는, JpaRepository를 상속받는 인터페이스를 만들기만 하면 스프링이 알아서 해당 인터페이스에 대한 구현체를 생성하고 IoC 컨테이너에 띄워줌. 이 과정에서 개발자가 직접 구현체를 만들거나, import 구문을 추가할 필요는 없다. 엔티티 매니저(EntityManager) 또한 스프링 데이터 JPA를 사용하면 실제로 엔티티 매니저를 직접 다루지 않아도 된다. (생략 가능) 레파지토리 인터페이스가 내부적으로 엔티티 매니저를 사용하여 데이터를 관리하기 때문
💡
JPA레파지토리라고 하면 알아서 IoC에 띄워주기 때문에 import도 필요없음 엔티티 매니저도 안 적어도 괜찮다. (근데 import, em 적어도 된다!)
 

save_test

package shop.mtcoding.blog.user; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; //import 필요없음 @DataJpaTest public class UserJPARepository { @Autowired private UserJPARepository userJPARepository; @Test public void save_test() { //given //빌더 덕분에 생성자를 건드릴 필요가 없다! User user = User.builder() .username("happy") .password("1234") .email("happy@nate.com") .build(); //when userJPARepository.save(user); //then } }
 

findById_test

@Test public void findById_test(){ // given int id = 1; // when Optional<User> userOP = userJPARepository.findById(id); if(userOP.isPresent()){ User user = userOP.get(); System.out.println("findById_test : "+user.getUsername()); } // then }

[ findById는 Optional타입이라 return을 User로 못 받는다 ]

notion image
💡
에러남
notion image
💡
findById를 보니… 옵셔널 타입이네?
notion image
💡
Optional<User> 라고 작성해주자!
 

findAll - order by (userJPARepository에 없는 메소드지만… 공부용으로!)

[ Sort 객체를 걸자 ]

notion image
💡
쿼리문을 조회했는데 order by가 안 걸려있다 → findAll에 Sort 객체 걸려있는 것 확인했죠? → 이 sort 객체를 걸어서 넘겨주면 됨!
notion image
💡
Sort는 [ org.springframework.data.domain ] 이다!! 이걸 걸어야 함!
 

[ findAll_test 코드 ]

방법 1)

@Test public void findAll_test() { //given //when userJPARepository.findAll(Sort.by(Sort.Direction.DESC, "id")); //then }
💡
뭐로 sort해줘야 하는지 적어줘야함! (ex. “id”)
notion image
💡
쿼리문에 order by 걸려서 날아가는 것 확인!
 

방법 2)

notion image
💡
한 번에 적지 않고, sort를 given에 기입
 

findByUsernameAndPassword → 따로 만들기

이런건 우리가 UserJPARepository에 따로 만들어야 한다. JPARepository는 findAll, findById, deleteById, save 딱 이 4가지만 해준다 * update는 더티체킹하는 거라 만들어주지 않음.
 

[ 따로 만들러 가자 → UserJPARepository ]

package shop.mtcoding.blog.user; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.repository.query.Param; //자동 컴퍼넌트 스캔이 된다 public interface UserJPARepository extends JpaRepository<User, Integer> { //@Query("select u from User u where u.username = :username and u.password = :password") //추상 메소드 생성 User findByUsernameAndPassword(@Param("username") String username, @Param("password") String password); }
💡
username과 password를 입력으로 받아 데이터베이스에서 해당 정보와 일치하는 User 엔티티를 찾아 반환하는 기능
간단한 쿼리는 @Query 여기다가 위의 예시처럼 적어도 됨 근데 동적쿼리처럼 복잡한 쿼리들은 레파지토리를 '엔티티명JPARepository' OR 'QueryRepository' 이런걸 따로 만들어서 처리해라. @Query("select u from User u where u.username = :username and u.password = :password") 이걸 다 적는거... 귀찮지 않니? findByUsernameAndPassword 메소드 하나면 생략 가능 (간단한 쿼리 메소드이기 때문에 사용하는 것!!)
💡
[ findByUsernameAndPassword ] 이 카멜이 꺾이는 것을 보고 쿼리를 만들어준다. → 이런게 바로 쿼리 메소드 (링크) → 오타내면 안 되겠죠?
 

@Param 어노테이션

메소드의 파라미터가 쿼리에 사용될 때 어떤 이름으로 매핑될지를 지정해줌. 즉, 해당 쿼리에서는 :username, :password로 사용됨 -> SQL 쿼리의 파라미터와 메소드의 파라미터를 명확히 연결 가능!
 

[ 다시 테스트하러… ]

@Test public void findByUsernameAndPassword_test() { //given String username = "ssar"; String password = "1234"; //when userJPARepository.findByUsernameAndPassword(username, password); //then }
 
 
Share article

codingb