본문 바로가기

FastCampus - 한번에 끝내는 Java|Spring 웹 개발/04 JPA

JPA Ch 2 SprDatJPA 기초 - 패스트캠퍼스 챌린지 18일차

기초 맛보기 가즈아


글 한 번 날려먹음. 나 좀 지금 당황스러운게 자동저장도 없고 글은 과거버전이네요... 뭐 어쩌겠어요 복구해야죠... 현실부정이다 현실부정이야 글 돌아와 ㅠㅠ

그래서 글이 좀 담백할거니 이해 부탁드립니다.

쉬익 쉬익 왜 날아갔는지 알았어
이미지랑 아래 필수내용 박스를 같이 복붙해서 이미지가 없는 거 취급받아서 뭔가 버그를 자극한거야


Spring Data JPA 를 처음 실제로 사용해보는 만큼, Entity 와 Repository 를 만들고 여러 API로 조회해보는 거까지 진행합니다.

생각보다 강의가 깁니다. 실습이 두 파트인데 결국 다 진행 못 하고 중간까지만 진행함

Entity / Repository 만들기

엔티티와 리포지터리를 만들어봅니다.

  • Entity
    • 클래스에 @Entity
    • p.key 에 @Id
  • Repository - 특이하게도 인터페이스만 만듭니다.
    • interface MyRepo extends JpaRepository<MyEntity, MyPKeyType>
    • 글 중간저장했는데 또 날라갔어...
    • 강의에서 JpaRepository 를 쭉 따라올라가서 API 리스트를 탐방했습니다.
      • 제가 궁금했던건 API의 네임스페이스였는데, Jakarta 꺼는 하나도 없고 전부 Spring 이었습니다. 왜일까...

테스트 클래스 자동으로 만들기 - kotlin 에디션 (tm)

이전 강의처럼, 이번 강의에서도 MyRepository 의 테스트 클래스를 IntelliJ의 기능으로 자동으로 만들었습니다.

kotlin 으로 따라해보려고 했는데 kotlin 으로 만든 MyRepository 로는 자동생성이 안 되더라구요.

우회방법은 MyRepository 도 Java 로 만들고, 테스트를 생성한 뒤 둘 다 kotlin 으로 변환해주는 거였고, 필드의 @Autowired 가 lateinit var 가 아니라 val 이라는 점만 빼면 괜찮았습니다.

Spring Data JPA API 써보기

트러블슈팅

일단 이 링크.

https://zzang9ha.tistory.com/371

강의의 Spring 버전이랑 다른 버전을 쓰다보니 (2.5) 동작 변경 때문에 트러블슈팅이 필요했습니다. 다음 섹션에 나오는 내용을 해보려면 아래의 프로퍼티를 꼭 넣어주세요. 자세한 내용은 위 링크.

(아 글 아까 다 썼다고 인텔리제이 껐다고 티스토리야... 다시 켜야되잖아...)

spring.jpa.defer-datasource-initialization=true

데이터 초기화

특정 파일을 추가하면 프로그램의 실행시마다 데이터베이스의 초기화를 위해 sql 명령어를 실행할 수 있습니다.

resources/data.sql

테스트에 추가하면 테스트의 실행 전에 실행됩니다.

call next value for hibernate_sequence;
insert into user (`id`, `name`, `email`, `created_at`, `updated_at`)
values (1, 'martin', 'martin@fastcampus.co.kr', now(), now());

call next value for hibernate_sequence;
insert into user (`id`, `name`, `email`, `created_at`, `updated_at`)
values (2, 'martin2', 'martin2@fastcampus.co.kr', now(), now());

call next value for hibernate_sequence; 가 이상할 수 있는데, auto increment 때문이라더군요. 나중에 배운다고 왜 필요한지만 보여주시고 넘어갔었습니다.

Spring Data JPA API 써보기 (진짜로)

(마음속: 지친다 똑같은 거 두 번 쓰는 거 너무 힘드니까 너희가 알아서 읽어)

  • 특이한 거 1: Sort.by()
  • 특이한 거 2: getById vs findById
    • lazy fetch: getById (getOne 은 deprecated)
      • 메서드에 @Transactional 필요 (이거 Spring 꺼 써야합니다)
      • kotlin 에서는 @Transactional 이면 메서드가 open 이어야 한다는 경고가 추가로 나왔습니다. 하긴 기본이 상속안함이니까... 가 중요한 게 아니고 상속을 활용한다는 점이 동작 방식을 유추하게 해주죠.
    • eager fetch: findById
    • 단어만 봐도 여기저기서 많이 본 영단어들이라 대충 뭔지는 순식간에 이해했는데 다음에 설명한다고 자세한 설명은 스킵하셨습니다. 그런데도 소스를 파고들어가서 보여주기까지 하셨는데... 좋다고 해야할까... 뭐 미리 보고 가면 좋죠.
      • getById -> em.getReference -> 프록시 객체를 받아온다 이말이야~
      • findById -> em.find
  • 특이한 거 3: kotlin 에서는 필요없지만, Java 를 짠다고 하면 arrayListOf() 대신 AssertJ 에 있다는 유틸리티 메서드 활용 가능 (안 써봄)
@SpringBootTest
internal open class UserRepoTest {
    @Autowired
    private lateinit var userRepo: UserRepo

    @Test
    @Transactional
    open fun crud() {
        val result = userRepo.findAll(Sort.by(Sort.Direction.DESC,"name"))
        result.forEach { println(it) }

        val resultIds = userRepo.findAllById(arrayListOf(1, 2, 5))
        resultIds.forEach { println(it) }

        userRepo.saveAll(arrayListOf(User("omg", "omg@omg.com"), User("oh", "oh@omg.com")))
        val resultSaved = userRepo.findAllById(arrayListOf(6, 7))
        resultSaved.forEach { println(it) }

        val getOneResult = userRepo.getById(1L)
        println(getOneResult)

        val findByIdResult = userRepo.findById(1L).get()
        println(findByIdResult)
    }
}

추가 프로퍼티

SQL을 읽으면 이해가 된다 이말이야~

properties 아래는 자유포맷이라 자동완성도 잘 안 된다고 잘 넣으라고 하시네요.

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

원래 있던 거
spring.h2.console.enabled=true
spring.jpa.defer-datasource-initialization=true
본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.
패스트캠퍼스: https://bit.ly/37BpXiC

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #한번에끝내는JavaSpring웹개발마스터초격차패키지Online

글을 다시 다 채워넣은 현재, 오늘이 끝나기 18분 전입니다. 쉬익 쉬익 글 복구하는데 30분 걸렸잖아... 티스토리 진짜...