월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결실전! 스프링 데이터 JPA
질문드립니다.
9:17초에서 changeTeam 함수를 보다가 문득 질문이 들어 질문 남깁니다. 함수명 자체는 팀을 '바꾼다'는 의미를 가지고 있는데 list에 add를 해주는 방식(team.getMembers().add(this))으로 구현하셨습니다. 그러면 리스트에 있던 기존 데이터객체의 jpa에서 알아서 update되는지, 아니면 무시하고 새로 add 되는지 궁굼합니다.
- 미해결실전! 스프링 데이터 JPA
spring data jpa 강의 수강 도중 질문입니다.
강의를 즐겁게 보며 학습하는 학생입니다. 개발 도중 테스트 실행 결과가 영한님처럼 잘 나오지 않고 이상하게 나오는 문제가 있는데요, 이럴땐 어떻게 해야 잘 볼 수 있을까요?? 감사합니다. https://github.com/dkyou7/JPA_data-jpa
- 미해결실전! 스프링 데이터 JPA
CollectionTable사용시 fetch 조인에 대해서
안녕하세요! 기본 빼고는 전부 완강했습니다. 좋은 강의 감사합니다! 강의를 다듣고 여러가지 실습을 해보고 있는데요. OneToMany 일대다 fetch조인은 하나의 테이블에 대해서 밖에 안되는데 일대다 관계의 CollectionTable조인은 여러 테이블에 대해서도 에러가 안나고 N+1 문제도 발생하지 않더군요. CollectionTable도 결국은 테이블에 대한 조인인데 왜 문제 없이 테이터를 가지고 올 수 있는지 궁금합니다.
- 미해결실전! 스프링 데이터 JPA
Member member로 바로 받아서 출력 질문있습니다!
안녕하세요 영한님. 진행 중에 출력이 잘 되지 않아서 질문드립니다. @GetMapping("/members2/{id}") 이 부분을 Member member로 바로 받아서 return member.getUsername()을 해보니깐 1 만 출력이 되길레 member 를 print 해보았더니Member(id=null,username=1,age=0) 라고 뜹니다.DB에는 정확히 들어가 있는 것은 확인되는 상태입니다. 무엇이 문제일까요 ??
- 미해결실전! 스프링 데이터 JPA
JPA/Hibernate 관련 property 문의
안녕하세요. 매번 친절한 답변 감사드립니다~ 상용 서비스에 적용한다고 할 때 JPA/Hibernate 관련 property 들 중에서 특별히 주의해서 설정해줘야할 것들이 있을까요? 강의에서 말씀해주신대로 DDL 관련 property들은 none으로 해줘야하고, open-in-view 같은 것에 대한 설정값, dialect들은 실제 운영DB에 맞게 명시적으로 설정해주는 것이 더 좋나요? 현업에 적용시 주의해야할 property들이 또 있는지, 또는 특별히 설정해서 사용하시는 property가 있는지 궁금합니다.
- 미해결실전! 스프링 데이터 JPA
마지막 부분 질문드립니다.
안녕하세요 !! 마지막 부분 궁금한 점이 생겨서 질문드립니다. 벌크를 사용하면 db에 바로 때려버린다고 하셨는데, //given ~~~~~ 5개 //when int resultCount=memberRepository.bulkAgePlus(20); em.flush(); em.clear(); 이 상황에서 먼저 벌크연산을 통해 db 값을 수정을 하고, flush와 clear 연산을 하게되는데, 이 상황에서의 flush 연산의 동작이 궁금합니다. 책에 따르면, 변경 감지가 동작해서 영속성 컨텍스트에 있는 모든 엔티티를 스냅샷과 비교해서 수정된 엔티티를 찾는다. 수정된 엔티티는 수정 쿼리를 만들어 쓰기 지연 SQL 저장소에 등록한다. 이 쿼리를 db에 전송한다. 라고 나와 있습니다. 먼저, save를 하는 과정에서 persist 한 member들 중 20이 넘는 것들은 member3 20member4 21member5 40 이 있습니다. persist 이후 bulk연산으로 db에 바로 값을 변경시키고, flush에 들어서게 되면 스냅샷 자체는 20,21,40 으로 되어있고 영속성컨텍스트에 따로 값을 변경하지 않았으니 수정된 엔티티를 찾지 못하고, 수정쿼리를 만들어서 지연 SQL 저장소에 등록하지도 않았을 것이고, 이곳에 등록된 것이 없으니 db에 전송하는 쿼리문도 없기 때문에 bulk 연산으로 수정된 값이 남게 되는 것인가요 ? 그렇다면 이 부분에서 flush는 스냅샷과의 비교를 했을 뿐 변경된 엔티티를 감지하지 못하였기 때문에 사실상 비교의 역할만 했다고 볼 수 있는건가요? 제가 이해한게 맞나 궁금합니다!! 긴 질문 읽어주셔서 감사합니다.
- 미해결실전! 스프링 데이터 JPA
totalcount 질문 드립니다.
안녕하세요!!! 20분대에서 말씀하시는 totalCount를 가져오는데에 있어 말하는 성능이슈는 page.getTotalElements와 연관이 있는건가요 ?? 그렇다면 count 쿼리를 분리하였을 때에 getTotalElements() 메서드는 이 분리한 count쿼리에서 결과값을 가져오는 것인가요 !?
- 미해결실전! 스프링 데이터 JPA
JpaRepository 기본 메서드에 대해
안녕하세요! 이번강의를 듣다가 궁금한 점이 있었습니다. 메서드의 이름을 통해 자동으로 내부가 구현되어서 동작을 할 수 있는데, 그렇다면 기존에 선언이 되어있는 save 라던가 delete 이런 것들도 동일한 방식으로 즉각적으로 구현이 되어서 동작이 이루어지는 건가요 ??
- 미해결실전! 스프링 데이터 JPA
안녕하세요 벌크 수정 쿼리 em.flush() 질문입니다.
안녕하세요, 좋은 강의 만들어주셔서 감사합니다. 강의듣다가 궁금한것이 생겨 질문드립니다. em.flush() 전에 벌크 수정쿼리를 날려 db에는 41살, 1차캐시에는 40살인데 em.flush()를 하면 db가 40살로 바뀌는게 아닌가요? 결과값이 41로 나온걸로 봐서는 제 생각에는 1차 캐시에 변경이 없기 때문에 flush해도 쿼리가 안나가건가 싶습니다. 명확하게 와닿지 않아 질문드립니다. 감사합니다.
- 미해결실전! 스프링 데이터 JPA
fetch join 시 child table 조건이 실제 쿼리에 반영이 안되네요..
[LneQuest] @Entity(name = "LneQuest") @Table(name = "lne_quests") @Cacheable @JsonInclude(JsonInclude.Include.NON_NULL) //@NamedEntityGraph(name = "LneQuest.all", attributeNodes = [NamedAttributeNode("quizList")]) class LneQuest ( var type: String, var title: String, var description: String?, @Column(name = "user_constraints") var userConstraints: String = "{}", @Column(name = "reward_total") var rewardTotal: Double, @Column(name = "reward_remain") var rewardRemain: Double, @Column(name = "reward_amount") var rewardAmount: Double, @Column(name = "reward_currency") var rewardCurrency: String, @Column(name = "thumbnail_url") var thumbnailUrl: String, @Column(name = "start_at") var startAt: LocalDateTime, @Column(name = "end_at") var endAt: LocalDateTime, @Column(name = "deleted_at") var deletedAt: LocalDateTime? = null, @OneToMany(fetch = FetchType.LAZY, mappedBy = "quest" /* , cascade = [CascadeType.ALL] */) var quizList: MutableList<LneQuiz> = mutableListOf() ): AbstractJpaPersistable1() { // 연관관계 추가 method 는 만들어 놓는게 편리하다. fun addQuiz(quizz: LneQuiz) { quizz.quest = this quizList.add(quizz) } } @Entity(name = "LneQuiz") @Table(name = "lne_quizzes") @Cacheable @JsonInclude(JsonInclude.Include.NON_NULL) open class LneQuiz( @JsonIgnore @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "quest_id") var quest: LneQuest, var type: String, var title: String, var description: String? = null, var answers: String? = null, @Column(name = "correct_answer") var correctAnswer: String, @Column(name = "deleted_at") var deletedAt: LocalDateTime? = null ): AbstractJpaPersistable() { } @Query("select q " + " from LneQuest q INNER JOIN FETCH LneQuiz qz where 1=1 " + " and (:type is null or qz.type = :type) " + " and (:from is null or :from < q.createdAt) " + " and (:to is null or q.createdAt < :to)", nativeQuery = false) fun findAllByJpql(@Param("type")type: String?, @Param("from")from: LocalDateTime?, @Param("to")to: LocalDateTime?, pageable: Pageable): Page<LneQuest> 페치 조인하니까 N+1 문제가 없이 쿼리 1번만 가는데요 조인되는 Child 테이블 컬럼 조건이 반영이 안되네요...;;; qz.type = :type Child 테이블 컬럼 조건을 넣어도 페치 조인 쿼리의 경우 Main 테이블 조건으로 들어가네요... 컬럼명이 같은게 있어서 그런건지요??? SELECT lnequest0_.id AS id1_0_0_, quizlist1_.id AS id1_1_1_, lnequest0_.created_at AS created_2_0_0_, lnequest0_.updated_at AS updated_3_0_0_, lnequest0_.deleted_at AS deleted_4_0_0_, lnequest0_.description AS descript5_0_0_, lnequest0_.end_at AS end_at6_0_0_, lnequest0_.reward_amount AS reward_a7_0_0_, lnequest0_.reward_currency AS reward_c8_0_0_, lnequest0_.reward_remain AS reward_r9_0_0_, lnequest0_.reward_total AS reward_10_0_0_, lnequest0_.start_at AS start_a11_0_0_, lnequest0_.thumbnail_url AS thumbna12_0_0_, lnequest0_.title AS title13_0_0_, lnequest0_.type AS type14_0_0_, lnequest0_.user_constraints AS user_co15_0_0_, quizlist1_.created_at AS created_2_1_1_, quizlist1_.updated_at AS updated_3_1_1_, quizlist1_.answers AS answers4_1_1_, quizlist1_.correct_answer AS correct_5_1_1_, quizlist1_.deleted_at AS deleted_6_1_1_, quizlist1_.description AS descript7_1_1_, quizlist1_.quest_id AS quest_i10_1_1_, quizlist1_.title AS title8_1_1_, quizlist1_.type AS type9_1_1_, quizlist1_.quest_id AS quest_i10_1_0__, quizlist1_.id AS id1_1_0__ FROM korbit.lne_quests lnequest0_ LEFT OUTER JOIN korbit.lne_quizzes quizlist1_ ON lnequest0_.id = quizlist1_.quest_id WHERE lnequest0_.type = 'multiple-choice' AND ( lnequest0_.created_at BETWEEN '2019-03-10T02:00:00.000+0000' AND '2020-03-10T02:00:00.000+0000' );
- 해결됨실전! 스프링 데이터 JPA
복합키 맵핑에 대해 질문드립니다
안녕하세요 권영한님 강의 너무 재미있게 잘 보고 있습니다! 😁 복합키 맵핑을 찾아보니 여러방법들이 있더라구요~ 영한님은 복합키 맵핑을 어떤 방법을 사용하시는지 질문 남깁니다.
- 미해결실전! 스프링 데이터 JPA
MemberRepository 클래스 생성시 에러
repository를 만들어서 MemberRepository 인터페이스를 만들었을 때 No bean named 'entityManagerFactory' available가 뜨네요... @EnableJpaRepositories(basePackages = "com.inf.learn.repository") 라고 설정도 했는데,,, 무슨 오류인지 잘 모르겠어요 컨트롤러단 에서는 entityManagerFactory를 만들고 있는데,,,왜 오류가 나는지 혹시 아실까요..?
- 미해결실전! 스프링 데이터 JPA
JpaRepository 사용시 Exception Handling
JpaRepository를 사용하는 경우, org.springframework.dao.DataAccessException은 RuntimeException을 상속해서 하위 Exception들은 모두 try-catch를 하지 않아도 compile상에는 문제가 없게 되버리는데요, API doc상에서 명시적으로 어떤 DataAccessException이 발생할지 기술되지 않아서 코딩하면서 exception handing에서 실수할 여지가 많아 보입니다. 일일히 개발자 스스로 발생 가능한 exception 찾아서 handling해야할지... 좀더 효율적인 방법이 있을까요? 가령, JpaRepository의 deleteById를 사용하는 경우 존재하지 않는 Id이면 EmptyResultDataAccessException이 발생하게 되는데, 이런 경우는 existById로 한번 체크하고 그냥 deleteById를 하는게 바람직한지 아니면 그냥 deleteById를 하면서 try-catch로 발생가능한 DataAccessException 종류를 다 잡아야하는지 애매하네요.
- 미해결실전! 스프링 데이터 JPA
@Query(""), 따옴표 내 경로표헌식 오류.
영한님의 강의를 따라가다 Query 어노테이션 부분에서 위와같이 강의에서와 달리 경로 표헌식이 먹히질 않습니다. 그래서 일일이 다 수기 작성을 하는 중인데, 구글에 검색을 해봐도 이런 오류에 대해서 언급한 곳이 없더라고요.. 해결 방법이 있을까요? (sdk 1.8, intelliJ 19.02 windows 유저입니다.)
- 미해결실전! 스프링 데이터 JPA
Unable to access lob stream 오류가 발생합니다.
다음과 같이 AccountRepository 인터페이스를 생성해 사용하는데, findByNickname 메소드에 대해 Unable to access lob stream 오류가 발생합니다. 검색해보니 맨 위 사진과 같이 Repository에 @Transactional을 추가하라는데, Clob이나 Blob이 포함된 엔티티는 해당 어노테이션을 반드시 사용해야 하는 것인가요? 혹시 맞다면 왜 그런건가요?
- 미해결실전! 스프링 데이터 JPA
낙관적 락 사용방법에 대한 질문
안녕하세요. 실무에서 비관적 락을 사용하던 것을 낙관적 락으로 변경하고자 하는데 잘 안되는 부분이 있어서 한참을 헤매다가 질문을 올립니다. 1. 기존에 version 필드가 없던 테이블에서 새로 version 필드를 추가할 때 ddl 을 어떻게 구성해야 할까요? alter table TABLE add version int default 1 not null; 이런식으로 default 값 1 에 not null 조건을 주어서 기존 데이터들의 버전을 1로 임의로 고정해놨는데요. 만약 기존 데이터의 마그레이션이 필요 없이 테이블을 새로 생성하는 상황 이라고 한다면 not null 이나 default 조건을 안줘도 jpa가 알아서 처음부터 insert 할때 version 1부터 잘 들어가나요? 2. 엔티티에 @Version 을 추가해서 NONE 모드의 낙관적인 락은 잘 동작하는것을 확인했는데요. 그런데 추가적인 옵션을 주고 싶어서 책에 언급된 Optimistic 를 이런식으로 조회에 추가해서 사용해 보았는데요. @Lock(LockModeType.OPTIMISTIC)Optional<Table> findById(Long id); 조회까지는 잘 되는데 문제는 가져온 이 엔티티에 변경이 이뤄질 때 무조건 다음과 같은 알 수 없는 에러가 발생합니다. 당연히 version 컬럼은 테이블에 잘 추가되어 있습니다. 다음은 문제가 발생할떄의 로그입니다. OPTIMISTIC 모드 이렇게 사용하는게 아닌건지.. Hibernate: select `version` from `TABLE` where `id` =? 2020-06-03 13:20:06.595 WARN [,,,] 1888 --- [ Test worker] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: S0022 2020-06-03 13:20:06.596 ERROR [,,,] 1888 --- [ Test worker] o.h.engine.jdbc.spi.SqlExceptionHelper : Column '`version`' not found. 3. 엔티티에 @Version 을 붙이면 기본적으로 그 엔티티가 낙관적인 락에 의해 수정시에 version 정보를 비교하는 로직이 추가된다고 이해를 했습니다. 그런데 특정 쿼리에 @Lock(LockModeType.OPTIMISTIC) 을 붙여주는 것은 그 쿼리를 통해 가져온 엔티티에만 추가적인 락 로직이 들어가고 만약 @Lock 이 안붙은 또다른 쿼리가 있다고 가정하고 그 쿼리도 실제 결과는 같은 엔티티를 내려준다고 했을때 후자의 쿼리로 가져온 엔티티는 NONE 모드 락만 적용되는 것이 맞을까요?
- 미해결실전! 스프링 데이터 JPA
도메인/DTO에 대해 질문드립니다.
반드시 DTO를 사용하라고 하셨는데. 하나의 도메인에 여러 개의 연관관계와 여러 개의 조회용 API가 있고, 각각 API에서 사용하는 연관관계가 다른 경우의 조언을 구하고 싶습니다. Ex) Member에 Region, Team 연관관계가 있고, 1번 API에서는 Region을, 2번 API에서는 Team을 fetch join 이런 상황에서 작업을 하다가 DTO 변환이나 쿼리 관련 에러가 발생하거나 API 스펙이 기억나질 않으면 '(1) 서비스 -> 도메인 확인 (2) DTO -> 도메인 확인 (3) Repository 쿼리 확인 -> fetch 대상 확인' 와 같은 복잡한 과정을 거치게 되네요. 이를 메소드명이나 클래스명으로 표현하기에 적합한 방법이 있을까요?
- 미해결실전! 스프링 데이터 JPA
테스트 공부를 위한 방법을 알 수 있을까요
늘 빛영한 님의 명강의 즐겁게 보고있습니다. 이동욱님의 도서와 영한님의 강의를 보며 테스트코드를 접하면서 대략적인 느낌으로 어떤역할을 하는지 왜 작성하는지를 미약하게나마 느끼고있지만 테스트코드에 대해 모르는 부분이 너무나 많은데요 테스트코드는 거의 필수처럼 여겨지는것으로 보이던데 테스트코드를 학습하기위해 혹시 추천해주고 싶은 책이나 그 외 자료 같은게 있으실지 궁금합니다!
- 해결됨실전! 스프링 데이터 JPA
JPA auditing 및 SOFT DELETE
안녕하세요 선생님 오랫만에 질문 올려보니다. JPA 사용할때마다 기억안나는 부분을 다시 항상 찾아보며 공부하고 있습니다. 그런던 중 궁금한게 생겨 질문 드립니다. 1.혹시 선생님은 soft delete 는 어떻게 구현하시는 지 궁금합니다.보통 (State 변수추가,deleteAt 컬럼으로 삭제 날짜 추가,deleted flag 변수 추가) 이 세가지인데 어느 방식을 선호하시는지요? 2 해당 구현은 repository 단에서 deleteById 이렇게 호출되면 엔티티를 조회한되 해당 값들을 업데이트 해주시나요?(@PreRemove 애노테이션을 사용해서나, createdAt 이나 lastModifiedAt처럼 Jpa Auditing을 활용해서 가능한가요?그리고 이렇게 하는게 더 깔끔할까요? 3.현재 Table A 의 생성,변경,삭제내역을 담은 Table History가 있다고 하고 일대다 관계로 아래처럼 되어있다고 하면 class Table A { @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) List<History> history; } 생성시 history.add(new History("생성")) 변경시 history.add(new History("변경")) 삭제시 history.add(new History("삭제")) 이러한 로직들은 생성은 생성자 안에, 변경은 변경을 하는 메서드 안에, 삭제는 soft delete시 수행되는 로직과 함께 두는게 나을까요 아님 @PrePersist @preUpdate 이러한 에노테이션을 붙혀서 Table A 안에 메서드를 만드는게 나을까요?
- 미해결실전! 스프링 데이터 JPA
@Query를 활용한 DTO 매핑
안녕하세요 김영한 강사님! "@Query값, DTO조회하기" 편에서 @Query 애노테이션을 활용해서 엔티티를 DTO와 매핑하는 것과 ModelMapper를 통해서 엔티티와 DTO를 매핑하는것과 실질적인 차이가 있는지 궁금해서 질문 드려봅니다 혹시 성능면이나 상황상 이번에 소개해주신 방법이 ModelMapper와 비교했을 때 유리한 점이 있나요? ModelMapper를 다루는 강의는 아니지만 기능이 유사한 것 같아 성능면의 차이가 있을까 해서 여쭤봅니다