30%
61,600원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결실전! 스프링 데이터 JPA
다중 조인 질문 드립니다.
t1, t2 ,t3 ,t4 각각 네개의 테이블이 있고 t1은 t2와 조인관계에 있고 t2는 t3와 t4에 조인관계가 있으나 t2와 t4는 id끼리의 조인관계가 아닙니다. 이럴 경우에는 어떤 식으로 진행해야 N + 1 문제가 발생하지 않을까요?
- 미해결실전! 스프링 데이터 JPA
페이징 관련 질문입니다.
안녕하세요! 16:39초 정도까지 강의를 듣다보면 DTO로 변환해서 넘기는 모습을 볼 수 있습니다. 그런데 응답값을 확인해보면 totalElements, last, size, number, sort, first, empty 등 페이징에 관련한 모든 필드들이 나가더라구요. 그냥 클라이언트에서 필요한 부분만 정제해서 내보내야할 것 같은데 실무에서는 어떠한 방법을 사용하나요?
- 미해결실전! 스프링 데이터 JPA
slice 관련 질문입니다
slice 의 경우 size 3으로 요청하면 limit 가 4로 나가는데요, 이렇게 하면 실제로 쿼리를 돌려보면 결과가 4개가 나옵니다. 그런데 content.size() 가 3이 나오는 이유는 뭔가요? 스프링데이터 JPA 에서 알아서 마지막 결과는 날려버리는 건가요?
- 미해결실전! 스프링 데이터 JPA
CQRS 리포지토리 질문
안녕하세요. 이전부터 말씀해주신 CQRS에 관해서 간단한 질문이 있습니다. 예를 들어 Member엔티티에 관해 아래처럼 2개의 레포지토리로 쪼갠다고 가정할게요. - MemberQueryRepository(읽기) - MemberCommandRepository(쓰기) 저희가 JPA Data의 이점을 살리려면 JpaRepository를 상속받아서 사용한다고 강의에서 배웠는데요. 읽기 관련 쿼리가 들어있는 Query와 쓰기 관련 쿼리가 들어있는 Command 2개의 레포 모두 JpaRepository를 상속받아서 사용하나요? JpaRepository에는 단순 find~로 시작하는 읽기 메소드뿐만 아니라 delete, save등 쓰기에 관한 메소드도 같이 들어가있어서 읽기/쓰기 레포에서 모두 상속받아서 사용한다면 나중에 작업을 할 때 단순 조회/저장/삭제 등을 어떤 레포에서 사용해야할 지 혼란이 올 것 같습니다. CQRS에 대해서는 이론만 알고있었지 실제로 적용해본적이 없어서 많이 혼란스럽네요. 감사합니다 :)
- 미해결실전! 스프링 데이터 JPA
Query() 어노테이션을 활용한 JPQL 질문입니다.
안녕하세요! 저는 현재 파이썬을 통해 실무를 하고 있습니다. 거의 모든 쿼리를 날릴 때 raw쿼리보다는 ORM을 사용해서 진행하고 있는데요. JPQL은 raw query까지는 아니지만 직접 sql문을 작성해야해서 많은 불편함이 있는 것 같아요. 이번 강의 다음이 querydsl이라 조금 달라질 것 같긴한데 아직 강의를 듣기전에 미리 질문드려봅니다. 질문 목록에서 확인해보니 실무에서도 @Query() 어노테이션을 활용하여 JPQL을 직접 적어주는 단순 쿼리를 자주 사용한다고 하셨는데요. querydsl의 경우 별도의 레포를 생성해줘야하기 때문에 발생하는 불편함은 있겠지만, ORM이 제공하는 가독성과 편리함은 그보다 더 많은 장점을 가져다 준다고 생각합니다. 질문을 요약하자면, 모든 레포에서 QueryDSL을 사용하는건 지양해야 할까요? 실무에서는 QueryDSL로 통일시키지 않고 말씀해주신 것 처럼 단순 쿼리의 경우 Query 어노테이션을 사용할까요? (물론 복잡한 쿼리의 경우 raw하게 나가야할테지만 제외하고 질문드려요) 감사합니다.
- 미해결실전! 스프링 데이터 JPA
Run 콘솔 하이라이트
안녕하세요! 로드맵대로 수강하다가 드디어 JPA Data 강의 듣고있습니다 ㅎㅎ 이전부터 궁금했던건데, 실행시키면 나오는 Run console에 하이라이트 적용되는 부분은 플러그인을 따로 받으신건가요? 그게 맞다면 플러그인 이름 좀 부탁드릴게요. 감사합니다 :)
- 미해결실전! 스프링 데이터 JPA
PK값을 이미가지고 있는 Entity를 DB에 저장하는 방법 문의
안녕하세요. Jpa린이 입니다. 좋은 강의 감사합니다. MSA형태로 Application을 구성하려고 합니다. 아래와 같은 경우에 2번DB에 save할때 Jpa가 내부적으로 pk를 가지고 먼저 select하는것 같은데, 2번DB에는 당연히 해당데이터가 없으니 에러가 발생하는 군요. PK 값을 가지고 있지만 select없이 바로 저장하게 할 수 있을까요? --아래-- 1번DB와 2번DB의 위치는 다르지만, 테이블구조와 데이터는 동일해야합니다. Eqp1Tr과 Eqp1TrDet는 1:N 구조입니다. 1번 App - 1번 DB에 저장 -> Kafka Publish (ID포함) 2번 App - Kafka Consume (ID포함) -> 2번 DB에 저장 <2번 App Consumer 와 Service 코드> @KafkaListener(topics = "${app.topic.name}", groupId = "${spring.kafka.consumer.group-id}")public void receiveMessage(@Payload Eqp1Tr eqp1Tr, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic, @Header(KafkaHeaders.RECEIVED_PARTITION_ID) Integer partition, @Header(KafkaHeaders.OFFSET) Long offset) { log.info("Received message: data = {}, topic = {}, partition = {}, offset = {}", eqp1Tr, topic, partition, offset); eqp1TrService.createTr(eqp1Tr);} public Eqp1Tr createTr(Eqp1Tr eqp1Tr) { log.info("eqp1Tr : {} {}", eqp1Tr.getEqp1TrDets(), eqp1Tr.getName()); List<Eqp1TrDet> eqp1TrDets = eqp1Tr.getEqp1TrDets().stream() .collect(Collectors.toList()); // Save at Eqp1Tr, Eqp1TrDet trRepository.save(eqp1Tr); trDetRepository.saveAll(eqp1TrDets); return eqp1Tr;} <Error> ... Hibernate: select eqp1trdet0_.id as id1_1_0_, eqp1trdet0_.createdBy as createdb2_1_0_, eqp1trdet0_.createdDate as createdd3_1_0_, eqp1trdet0_.col1 as col4_1_0_, eqp1trdet0_.col2 as col5_1_0_, eqp1trdet0_.tr_id as tr_id6_1_0_ from Eqp1TrDet eqp1trdet0_ where eqp1trdet0_.id=? 2021-04-24 00:05:45.319 TRACE 19496 --- [ntainer#0-0-C-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [2] 2021-04-24 00:06:25.719 INFO 19496 --- [ntainer#0-0-C-1] o.a.k.clients.consumer.KafkaConsumer : [Consumer clientId=consumer-tr-consumer-service-1, groupId=tr-consumer-service] Seeking to offset 3 for partition eqp.tr.ic.eqp1-0 2021-04-24 00:06:27.013 ERROR 19496 --- [ntainer#0-0-C-1] essageListenerContainer$ListenerConsumer : Error handler threw an exception org.springframework.kafka.KafkaException: Seek to current after exception; nested exception is org.springframework.kafka.listener.ListenerExecutionFailedException: Listener method 'public void me.kalpha.trconsumerservice.trmart.service.Eqp1TrConsumerService.receiveMessage(me.kalpha.trconsumerservice.trmart.entity.Eqp1Tr,java.lang.String,java.lang.Integer,java.lang.Long)' threw exception; nested exception is org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find me.kalpha.trconsumerservice.trmart.entity.Eqp1TrDet with id 2; nested exception is javax.persistence.EntityNotFoundException: Unable to find me.kalpha.trconsumerservice.trmart.entity.Eqp1TrDet with id 2; nested exception is org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find me.kalpha.trconsumerservice.trmart.entity.Eqp1TrDet with id 2; nested exception is javax.persistence.EntityNotFoundException: Unable to find me.kalpha.trconsumerservice.trmart.entity.Eqp1TrDet with id 2 ...
- 미해결실전! 스프링 데이터 JPA
카운트 쿼리 관련 질문드립니다.
안녕하세요 강사님, 강사님 강의 듣고 스프링을 이용해서 모바일 앱 프로젝트를 진행해보고있는 학생입니다! 다름이 아니라 화면을 구성하려던 중에, 구현에 궁금한 점이 생겨 질문드립니다. 앱들을 보면 메뉴창 같은것을 열었을 때, 카테고리별 항목 수가 보여지는 등 list의 카운트 수를 가져와야할 경우가 있는데요, 이런 경우에는 각 카테고리별 카운트들만 가져와서 반환하는 api를 하나 만드는게 좋은 방법일까요? 미리 각 데이터 리스트를 모두 페이징으로 가져와서, totalElements 수로 설정하는것은 비효율적이라는 생각이 들긴 하는데, 어떻게 하는것이 주로 쓰이는 방법인지 궁급합니다. 이러한 경우에 주로 사용되는 방법이 있나요? 강사님 강의중에 혹시 관련 내용이 있는 부분이 있다면 말씀해주셔도 좋습니다 항상 좋은 강의 감사드립니다.
- 미해결실전! 스프링 데이터 JPA
트랜잭션 동시성 이슈 관련 질문 드립니다.
안녕하세요 영한님! 스프링 관련 강의들 잘 듣고 있습니다. 항상 좋은 강의 감사합니다. 질문은 Transaction 과 lock 에 관련된 것인데요. 현재 멀티쓰레드로 Centercut을 돌리면서 해당 데이터에 대한 Key 를 채번하는데, Key를 채번하는 과정에서 동시에 호출이 발생할 때 무결성 예외가 발생하는 문제가 있었습니다. 현재 상황은 채번이 이루어지는 메소드가 호출될 때 마다 Transaction을 새로 생성하기 위해 @Transactional(propagation = Propagation.REQUIRES_NEW) 어노테이션을 붙였고, Repository에서 실제 Max 일련번호를 가져오기 위한 Select 쿼리에는 @Lock(LockModeType.PESSIMISTIC_WRITE) 다음과 같이 락 모드를 설정했습니다. 그런데 문제는 Select 했을 때 데이터가 존재하면 그 행에 대해 lock을 잡을 수 있지만 데이터가 없을 경우엔 locking 할 row가 존재하지 않아 동시성 문제가 발생하는 것 같습니다. (동시에 데이터가 없다고 인식하고 새로운 데이터 생성 후 insert 시도 => 무결성 제약조건 위배) 해결방법을 찾아 보니 메소드에 synchronized 를 붙이거나 try~catch 문으로 강제로 추가 수행하는 것 등이 나오는데 좀 더 나은 방법이 있을지 질문 드립니다. 감사합니다!!
- 미해결실전! 스프링 데이터 JPA
영속성 컨텍스트 관련 질문입니다.
매번 수준 높은 강의에 감사 드리고 열심히 공부하고 있습니다!! 그런 의미에서 질문이 있는데요, 1. 만약 MemberJpaRepositoryTest 에서 아래처럼 EntityManager 를 또 주입 받았을 경우 기존에 MemberJpaRepository 에서의 EntityManager 와 Test에서의 EntityManager 가 같은 영속성 컨텍스트를 바라보고 있는 건가요? 2. flush 이후에 clear 를 통해서 영속성 컨텍스트를 비우고 엔티티의 값을 변경하면, 1차 캐시에 객체가 없어서 변경감지가 일어나지 않기 때문에 update 가 발생하지 않는게 맞나요? 3. 그러면 혹시 2번에서 발생한 변경사항을 db에 반영할 수 있는 방법은 없을까요? 아니면 1차 캐시에 존재하지 않는 객체의 속성을 변경하려고 할 경우 에러를 낸다던지 하는 건 없을까요? class MemberJpaRepositoryTest { @PersistenceContext EntityManager newEm; @Autowired MemberJpaRepository memberJpaRepository; @Test public void basicCRUD() { Member member1 = new Member("member1"); Member member2 = new Member("member2"); memberJpaRepository.save(member1); memberJpaRepository.save(member2); newEm.flush(); newEm.clear(); member1.setMemberName("newMember1"); } }
- 미해결실전! 스프링 데이터 JPA
Unit Test 관련 질문입니다.
안녕하세요 영한님 ! 어제 h2 관련해서 질문을 드렸었는데요 좋은 답변 감사했습니다! 다름이 아니라 service unit test 를 하는 과정에서 repository 의 Pageable 을 mock 으로 주입해야 하는 상황이 왔습니다. 현재 junit 5 의 bdd 를 이용해서 테스트를 하고 있는데요, junit5의 bdd 역시 영한님은 잘 아시겠지만 given()을 이용해서 JpaRepository.findAll(Pageable pageable) 이 호출되면 willReturn() 으로 반환되는 반환 값을 가짜로 주입해야 하는 상황입니다. 하지만 여기서 어떻게 Page<Entity> pagedEntitied 를 주입해야 하는지 몰라 진행이 힘들더라구요 ㅠㅠ 수업의 방향과 상관 없는 내용이라 실례임을 인지하고 있지만 어떻게 해결해야 할지 도통 갈피를 못 잡아서 질문드려 봅니다.. import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; class MemberServiceTest { private MemberService memberService; private final MemberRepository memberRepository = mock(MemberRepository.class); @BeforeEach void setUp() { ModelMapper modelMapper = new ModelMapper(); modelMapper.getConfiguration() .setFieldAccessLevel(Configuration.AccessLevel.PRIVATE) .setFieldMatchingEnabled(true); memberService = new MemberService(memberRepository, modelMapper); // 문제의 willReturn 반환 타입.. 현재는 null을 넣어놨습니다. given(memberRepository.findAll(any(PageRequest.class))).willReturn(null); } @Test @DisplayName("모든 사용자 조회") void getMembers() { // when PageRequest pageRequest = PageRequest.of(0, 5); // then Page<MemberResponseData> pagedData = memberService.getMembers(pageRequest); assertEquals(pagedData.getSize(), 5); } } @Entity @Getter @Builder @AllArgsConstructor @NoArgsConstructor public class Member extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String email; private String password; private String nickname; public static MemberResponseData fromEntity(Member member) { return MemberResponseData.builder() .email(member.getEmail()) .nickname(member.getNickname()) .build(); } } // Page<MemberResponseData>에 해당하는 MemberResponseData(DTO) @Getter @Builder @AllArgsConstructor @NoArgsConstructor public class MemberResponseData { private String email; private String nickname; } // MemberService @Service public class MemberService { private final MemberRepository memberRepository; private final ModelMapper modelMapper; public MemberService(MemberRepository memberRepository, ModelMapper modelMapper) { this.memberRepository = memberRepository; this.modelMapper = modelMapper; } /** * 모든 회원을 조회한다. * * @param pageable : 페이징 정보 * @return 모든 회원 */ public Page<MemberResponseData> getMembers(Pageable pageable) { return memberRepository.findAll(pageable).map(Member::fromEntity); } }
- 미해결실전! 스프링 데이터 JPA
h2 In-Memory에서 rollback
안녕하세요! 강의를 듣고 강의를 토대로 혼자 이것 저것 해보고 있는 학생입니다! 다름이 아니라 강의와 다르게 h2를 spring boot 가 실행 될 때 메모리에서만 동작하게 하고싶어서 JDBC URL 을 jdbc:h2:mem/test 라고 지정을 했습니다. 그리고 문제는 @Test 어노테이션이 붙은 테스트 클래스에서 발생하였는데요, RepositoryTest 에서 @Transactional과 @Rollback(false) 를 추가시켰음에도 불구하고 spring boot가 돌아가는 8080/h2-console 에서는 자동으로 rollback이 되는데, 혹시 어떤게 문제인지 알 수 있을까요? // MemberRepositoryTest @SpringBootTest @Transactional @Rollback(false) class MemberRepositoryTest { @Autowired private MemberRepository memberRepository; @Test @DisplayName("이메일로 조회") void read() { // given String email = "dhslrl321@gmail"; String password = "hwi199"; String nickname = "dhslrl321"; Member member = Member.builder() .email(email) .password(password) .nickname(nickname) .build(); memberRepository.save(member); // when Optional<Member> memberOptional = memberRepository.findByEmail(email); // then memberOptional.ifPresentOrElse( m -> assertEquals(nickname, m.getNickname()), Assertions::fail ); } } // application.yml spring: h2: console: path: /h2-console enabled: true settings: web-allow-others: true datasource: driver-class-name: org.h2.Driver url: jdbc:h2:mem:auth username: sa password: jpa: hibernate: ddl-auto: create-drop properties: show_sql: true format_sql: true
- 미해결실전! 스프링 데이터 JPA
jpa merge 관련 문의 드립니다.
안녕하세요. 항상 좋은 강의 감사드립니다. 새로운 엔터티를 구별하는 방법에서 궁금한 부분이 있어 질문 드립니다. 일반적으로 수정을 위해 findById를 통해 Entity 객체를 영속화 시킨 후 필요한 칼럼을 변경처리 하고 있습니다. 이러면 변경감지를 통해 트랜잭션 종료 구간에서 자동 update 쿼리가 발생이 되는데요... 만약 이 상태에서 repository.save(entity)를 수행하게 되면 혹시 문제가 발생할 만한 포인트가 있는지 궁금합니다. 내부 로직을 보면 아마도 save()에서 SPring Data JPA가 merge를 수행할것 같은데요... 보통 준영속성 상태 객체를 merge하는건 좋은 방법이 아닌것 같지만 이 처럼 findById를 통해 영속화 되어 있는 객체를 merge 하게 되면 혹시나 별도 주의사항이 있지는 않는지 문의 드립니다. 감사드립니다.
- 미해결실전! 스프링 데이터 JPA
안녕하세요 선생님!
안녕하세요 선생님 강의 잘 듣고 있습니다. 어느새 선생님 강의를 다 듣고 이제 데이터 JPA, 쿼리dsl만 남겨놓고 있습니다. 지금 데이터JPA를 들으면서, 제가 과연 데이터 JPA를 이용해서 생략한 코드들을 제가 자유자재로 짤 수 있을까에 대한 의문이 생깁니다. 실무에서 당연히 data jpa를 사용한다고 하지만 저 혼자서 jpa코드도 짜본적 없이 data jpa를 사용해도 될지 잘 모르겠습니다. 원래는 jpa 실전1까지 강의를 듣고 토이프로젝트를 바로 시작하려다가 다른 분께서 똑같은 질문을 남긴것에 대한 선생님의 답변을 봤었는데, 그때 선생님께서 강의를 다 듣고나서 진행해야 시간낭비가 덜 하다고 하셨습니다. 그래서 강의를 다 듣고 토이프로젝트를 진행하려고 계획을 했지만, 지금 data jpa 강의를 들으면서 앞서 언급드린 의문이 생깁니다. 그래서 제 생각에는 동적쿼리 문제는 결국 쿼리dsl로만 해결하는것이 국룰이니까 쿼리dsl까지만 듣고 토이프로젝트를 시작하는 것이 좋지 않을까 합니다. data jpa는 실무에서 필수이긴 하지만 당장 배우지 않는다고 엄청나게 큰 손해를 보는 것은 아닌것 같습니다. 그래서 제 결론은 1. data jpa, 쿼리dsl 강의만 남겨놓은 상황에서 바로 토이프로젝트(동적쿼리를 사용하지 않는 토이프로젝트) 진행 후 남은 두 개의 강의를 진행하는것 2. 쿼리dsl까지 듣고 토이프로젝트 진행 후 데이터 jpa를 진행하는 것 3. 그냥 강의를 다 듣고 지금까지 배운 기술들을 합친 토이프로젝트를 진행하는것 중에 선생님께서는 어느것을 추천하시는지 여쭙고싶습니다! 긴글 읽어주셔서 감사합니다!!
- 미해결실전! 스프링 데이터 JPA
MySQL의 JSON타입에 관해서
강의 재밌게 잘 보았습니다. 감사합니다. 한가지 문의 드리고 싶은 내용이 있어 여기에 글 올려봅니다. Entity중 객체 타입 속성을 json으로 변환해서 MySQL db의 json타입 컬럼으로 다루고 싶은데 어떻게 하면 될까요? 구글링 해보면 JPA의 conver로 해결 된다고 해서 아래와 같이 시도해보고 있는데 잘 안되네요.. 혹시 좋은 방법 있을까요. @Entity class ItemEntity { @Id @GeneratedValue private Long id; @Convert(converter = BookJsonConverter.class) private BookJson bookJson; } @Data class BookJson { private Long id; private String name; } class BookJsonConverter implements JsonConverter<BookJson> { // 이렇게 하는 이유는 BookJson같은 애들이 너무 많아서.... } public interface JsonConverter<T> implements AttributeConverter<T, String> { @Override default String convertToDatebaseColumn(T dataObj) { return new ObjectMapper().writeValueAsString(dataObj); } @Override default T convertToEntityAttribute(String dbData) { return new ObjectMapper().readValue(dbData, new TypeReference<>() {}); // <---- 여기서 hashMap을 반환하면서 결국 BookJson으로 cast시 에러 발생..... } }
- 해결됨실전! 스프링 데이터 JPA
fetch join 수행시 우선순위?
항상 강의 잘 듣고 있습니다. 감사합니다! fetch join을 할 때 기본적으로 left outer join이 수행된다고 하셨는데 그 전 강의에서는 대부분 Inner join으로 수행됐던것같아서. 질문드렸습니다! 수행하는 우선순위가 따로 있는건가요?
- 미해결실전! 스프링 데이터 JPA
PDF 오류일까요?...
안녕하세요. 강의영상 소스코드와 PDF 소스가 꼭 맞아야되는지는 모르겠으나...실습하면서 잠깐 헤매서 내용 공유드립니다. 영상에서 @Query 등록시 @Query("select new study.datajpa.dto.MemberDto PDF 내용 @Query("select new study.datajpa.repository.MemberDto
- 미해결실전! 스프링 데이터 JPA
연관관계매핑에서 @ManyToOne의 Id
삭제된 글입니다
- 미해결실전! 스프링 데이터 JPA
스냅샷이란..?
선생님 강의 정말 잘 듣고있습니다!! 선생님이 QueryHint에서 readOnly를 켜주면 " 스냅샷을 안찍죠 . . . " 이러셨는데 이떄 스냅샷이 JPA 영속성컨텍스트(1차캐시) 를 의미하는 건가요?
- 미해결실전! 스프링 데이터 JPA
선생님 pdf파일 55페이지 오타있어요
Pageable, Page를 파리미터와 응답 값으로 사용히자 않고 => Pageable, Page를 파리미터와 응답 값으로 사용하지 않고