30%
61,600원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
트랜잭션의 범위와 준영속 상태
안녕하세요 강의를 수강하다 제가 잘못 이해하고 있는 부분이 있는 것 같아서 질문드리게 되었습니다.다음은 "간단한 주문 조회 V2: 엔티티를 DTO로 변환" 강의에서 35초에 해당하는 화면을 캡처한 부분입니다.orderRepository는 @PersistenceContext 처리된 EntityManager를 가지고 있는데 이 때 Transaction의 범위가 어디까지인지를 잘 모르겠습니다.추측으로는 List<Order> all가 준영속상태로 반환될 것으로 예상했는데 order가 membe프록시 객체를 가지고 있다가 Lazy 강제 초기화가 가능한 것을 보면 영속성 컨텍스트가 여전히 존재하는 상태인 것 같습니다.Transaction의 범위가 어디까지인지 궁금합니다.감사합니다.
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
DTO를 Result<T>에 담아서 반환할 때의 제너릭 표기 여부
안녕하세요DTO를 직접 반환하지 않고 Result로 감싸서 반환하는 것을 구현하는 도중 궁금한 점이 생겼습니다. 일단 코드는 다음과 같습니다./** * DTO를 감싸서 반환하는 클래스 * 반환에 성공하면 status에는 "success", data에는 DTO, error에는 null이 담긴다 * 예외가 발생하면 status에는 "fail", data에는 null, error에는 errorCode가 담긴다 */ @NoArgsConstructor @Getter public class Result<T> { private String status; private T data; private ErrorDTO error; public Result(String status, T data, ErrorDTO error) { this.status = status; this.data = data; this.error = error; } } @PostMapping("/save") public ResponseEntity<Result<UserDTO>> save(@RequestBody @Validated UserDTO userDTO, BindingResult bindingResult) { if (bindingResult.hasErrors()) { for (ObjectError error : bindingResult.getAllErrors()) { return ResponseEntity.ok().body(ResultUtils.fail(error.getCode(), error.getDefaultMessage())); } } UserDTO savedUserDTO = userService.save(userDTO); return ResponseEntity.ok().body(ResultUtils.success(savedUserDTO)); }public class ResultUtils { private static final String SUCCESS = "success"; private static final String FAIL = "fail"; public static <T> Result<T> success(T data) { return new Result<>(SUCCESS, data, null); } // 이 메서드의 제너릭 표기도 어떻게 해야할지...? public static Result fail(String errorCode, String message) { return new Result(FAIL, null, new ErrorDTO(errorCode, message)); } } 이렇듯 예외가 발생한 경우에 data에는 null을 담아서 반환하고 싶으면, 예외 발생 여부에 따라 Result<T>의 T가 userDTO이기도 하고 null의 2가지...? 인 느낌이 드는데 그럼 public ResponseEntity<Result<UserDTO>> save처럼 메서드 선언부에서 Result의 제너릭을 표기하는 의미가 있을까요? Result로 적는 것이 좋을지 그래도 userDTO를 명시해 줘야할지가 궁금합니다. 추가로 userDTO 단건일시에는 제너릭이 그다지 복잡하지 않지만 만약 DTO에 페이징 기능을 더하여 반환하고자 한다면 Result<Page<UserDTO>> 처럼 제너릭 안에 제너릭이 있게 될텐데 이러한 경우에도 그냥 제너릭을 생략하는 것이 좋을지 궁금합니다!
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
@OneToOne(mappedBy)의 쿼리 최적화 방법
안녕하세요!OneToOne(mappedBy = ...)와 관련한 질문을 드립니다.위와 같이 mappedBy로 되어있는 엔티티를 조회하게 되면, LAZY로 설정하여도 반드시 즉시로딩됩니다. 또한, default_batch_fetch_size도 적용되지 않아 반드시 N+1문제가 발생하는 것으로 알고있습니다.여기서 생기는 고민이, 특정 엔티티의 목록을 조회하는 로직을 구현할 때 엔티티를 select절에 넣는것에 대해서 조금 조심스럽습니다. (단건 조회는 즉시로딩이 발생해도 상대적으로 문제의 심각도가 적음)현재 목록을 조회하려는 엔티티에 OneToOne(mappedBy = ..)가 없다면, 엔티티의 목록을 조회해도 N+1 문제와 무관합니다. 하지만, 미래에 추가가 된다면 성능에 문제가 없던 것들도 N+1문제가 생길 수 있습니다.이에 대한 한 가지 해결방법은 Querydsl의 Projection을 사용하는 방법이 있습니다. 이는 결국 select절을 입력해줘야하며 지연로딩과 @BatchSize을 통해 해결하는게 아니기 때문에, 더 복잡한 조인 쿼리를 작성해야할 수도 있습니다. 이로 인해 생산성도 낮아질 수도 있습니다. 정리하자면,select 절에 entity --> 다른 필드를 지연로딩 처리하여 더 쉽게 데이터를 찾지만, 미래에 발생할 수 있는 N+1문제를 어쩔 수 없이 수용한다.select절에 Dto Projection --> 조인 쿼리를 다 작성해야한다. Projection을 기입해야한다. 하지만, @OneToOne(mappedBy)가 추가되어도 쿼리 성능에는 문제가 없다.양쪽의 트레이드 오프가 있는 것 같습니다. 현업에서는 어떠한 방법을 이용하나요? (추가적으로, mappedBy를 이용하지 않거나 하이버네이트에서 제공하는 바이트코드 조작 방법도 있네요)
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
트랜젝션 범위와 준영속 상태
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? ([예]/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? ([예]/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? ([예]/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.안녕하세요! 강의에서 [회원 수정 API] 파트에서 질문이 있어 이렇게 문의드리게 되었습니다.트랜잭션 범위와 준영속 상태에 관한 질문입니다.우선 Service 계층에서 update에서 member 객체를 준영속 상태로 반환하도록 하였습니다.그 후 Controller 계층에서 PutMapping 방식으로 member의 이름을 "-newhello"로 변경하여 db에 반영하였고그 다음에 member객체의 이름을 "준영속 상태"로 변경 하였습니다. 이미 트랜잭션이 끝나면서 영속성 컨택스트가 종료되었다고 생각했고여기까지는 db의 값이 여전히 "-newhello"라는 것을 확인해서 문제가 없었는데 그 다음이 이해가 가지 않습니다.memberServie에서 findMember를 다시 조회하였는데이 객체가 member와 완전히 동일한 객체로 나옵니다.전 db에서 값을 가져와서 이름이 "-newhello"일 것으로 예상했는데 이렇게 된 이유를 모르겠습니다...마치 db와의 연동은 안되지만 영속성 컨택스트의 1차캐시에 남아있는 member 객체를 같은 id 식별자를 바탕으로 찾아온 것 같아서 혼란스럽습니다. ㅠㅠ
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
dto vo 개념이 너무 헷갈립니다.
회원생성 부분에서 @PostMapping("/api/v2/members") public CreateMemberResponse saveMemberV2(@RequestBody @Valid CreateMemberRequest request) { Member member = new Member(); member.setName(request.getName()); Long id = memberService.join(member); return new CreateMemberResponse(id); }CreateMemberRequest 가 dto라고 설명하셨는데회원가입시 json값은 값 변경이 없는데 vo가 아닌가요?
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
13:50쯤부터 EAGER로 변경하고 나서 N+1 동작 질문있습니다
fetchtype을 LAZY로 설정했을 경우 N+1문제는 이해했습니다. 그런데 EAGER의 경우 Order를 위한 1개의 select쿼리 뒤에 delivery를 위한 1개의 쿼리와 3중 조인문 2개의 쿼리가 나가고 있는데 (위 사진) join문이 EAGER처리를 위한 쿼리라면 왜 order 조회쿼리 뒤에 바로 나가지 않고 delivery 조회쿼리가 한번 나간 뒤에 나가는건지 왜 delivery에 대한 추가 쿼리는 나가는데 member는 조회쿼리가 나가지 않고 join문이 나가는지 EAGER의 경우에도 모든 연관객체가 영속성 콘텍스트 안에 존재하지 않는다면 정확히 1+N개의 쿼리가 나가는지 (=LAZY와 똑같이 1+N개의 쿼리가 나가는지) 이 세가지가 이해되지 않습니다.EAGER일때 쿼리를 이해해보려고 노력했는데 "LAZY와는 추가쿼리(N)가 나가는 시점의 차이가 있다" 정도 말고는 이해가 되지 않아 질문드립니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
PathVariable 사용이유..updateMemberV2메소드 질문입니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. MemberApiController 수정시 /** * 수정 */ @PutMapping("/api/v2/members/{id}") public UpdateMemberResponse updateMemberV2(@PathVariable("id") Long id, @RequestBody @Valid UpdateMemberRequest request) { memberService.update(id, request.getName()); Member findMember = memberService.findOne(id); return new UpdateMemberResponse(findMember.getName(), findMember.getId()); } @Data static class UpdateMemberRequest{ private String name; } @Data @AllArgsConstructor static class UpdateMemberResponse{ private String name; private Long id; } 수정할때PathVariable로 url주소에서 맵핑하셨는데그냥 @PutMapping(""/api/v2/members/")로 하고,UpdateMemberRequest 클래스에서 id를 필드로 추가한 후 @PutMapping("/api/v2/members") public UpdateMemberResponse updateMemberV2( @RequestBody @Valid UpdateMemberRequest request) { memberService.update(request.getId(), request.getName()); Member findMember = memberService.findOne(request.getId()); return new UpdateMemberResponse(findMember.getName(), findMember.getId()); } memberService.update(id, request.getName()); 가 아닌 memberService.update(request.getId(), request.getName());id를 PathVariable로 받지말고,request에서 받아서 설계해도 될까요?PathVariable을 사용하는 이유가 궁금합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
select 쿼리없이 dto 만들지 않은 이유
강의에서는 아래와 같이 select 쿼리를 이용해 업데이트 된 회원을 조회후 response로 전달해 주었는데 @PutMapping("/api/v2/members/{id}") public UpdateMemberResponse updateMemberV2(@PathVariable("id") Long id, @RequestBody @Valid UpdateMemberRequest request) { memberService.update(id,request.getName()); Member findMember = memberService.findOne(id); return new UpdateMemberResponse(findMember.getId(), findMember.getName()); }아래와 같이 하지 않은 이유가 있을까요??@PutMapping("/api/v2/members/{id}") public UpdateMemberResponse updateMemberV2(@PathVariable("id") Long id, @RequestBody @Valid UpdateMemberRequest request) { memberService.update(id, request.getName()); return new UpdateMemberResponse(id, request.getName()); }
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
generated 폴더와 Q class import에 관한...
[질문 내용]여기에 질문 내용을 남겨주세요.1. Tasks - other에 compileQuerydsl이 없어서 compileJava를 눌러서 했는데 괜찮은지 ??2.강사님과 다르게 build /generated 이렇게 생성되어도 문제가 없는지?저런식으로 Q파일들이 생성되었는데 import가 안되고 사용이 안되는 이유 알려주시면 감사하겠습니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
질문입니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 패치 조인은 즉시 로딩을 하는데, 필요한 테이블만 즉시 로딩을 한다고 이해하면 될까요?
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
PostConstructor 관련해서 질문있습니다!
안녕하세요 항상 강의 잘 보고 있습니다.영한님께서 알려주신 내용으로 공부와 토이프로젝트를 병행해나가다 이해가 가질 않는 부분이 있어서 질문드립니다.상황A클래스에 @PostConstructor 어노테이션을 붙여 객체 a를 미리 저장해 DB에 저장을 하고 B클래스에도 @PostConstructor를 붙여 객체 b를 저장하려 하였습니다.(A클래스와 B클래스의 연관관계는 일대다입니다.) a객체에 b객체를 리스트 형태로 저장할 수 있게끔 빈 리스트를 만들어 저장하는 것까지 A클래스에서 확인을 하였고 B클래스에서 b객체를 만들고 아까 저장한 a객체를 DB에서 가져오는것까지 확인하였습니다.이후 a객체와 b객체의 연관관계를 연관관계 편의 메서드로 만들어주려하였으나 a객체에서 b객체들을 담을수 있게끔 만들어둔 리스트 형식의 필드가 lazyinitializationexception 예외를 발생시키며 더미데이터 생성에 실패하였습니다.시도해 본 것들@OneToMany의 기본 로딩 전략이 지연로딩이기에 생긴 문제인가 싶어 em.flush, @GraphEntity, hibernate.initialize까지 해보았으나 똑같이 lazyinitializationexception를 발생시키며 더미데이터 생성에 실패하였습니다.(혹시나 해서 즉시로딩으로 변경하니 더미데이터 생성은 문제없이 잘 되었습니다.)궁금한 점혹시 어떤 이유로 다음과 같은 현상이 발생했는지 알 수 있을까요?
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
@BatchSize와 SQL Parsing
안녕하세요. 강의 잘 듣고 있습니다.BatchSize라는 기능을 배워서 상당히 놀라웠는데요.해당 기능을 사용해 실행되는 쿼리를 보니IN (?, ?)와 같이 바인딩 변수를 이용하는 것으로 보이는데만약 말씀하신것처럼 BatchSize를 1000개로 잡았다 할 떄최악의 경우 IN절 내부의 ? 바인딩 변수가 계속 변하게 된다면 (1개 ~ 1000개 )소프트 파싱의 이점을 살리지 못하는 경우가 발생할 수도 있나요 ??항상 좋은 강의 만들어주셔서 감사합니다
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
GetMapping에서 Required request body is missing 에러
안녕하세요UI와 GetMapping API 테스트를 하는데 로컬에서 테스트 할 때는 잘 되는데API 테스트를 하면 아래와 같이 Required request body 에러가 뜹니다.Client에서 보낸 JSON데이터를 로컬에서 테스트 하면 잘 되는데 GetMapping 만 쓰는 API에서는 @RequestBody 가 안되는걸까요..? (비슷한 내용의 코드인데 GetMapping, PUTMapping, POSTMapping이 있는 API에서는 또 잘되고 있어서 이런의문점이 듭니다.)아래 코드와 에러 내용 드립니다. . 코드 (Parameter 명과 Class명 수정했습니다.)@Slf4j@RestController@RequestMapping(value = "/", method = RequestMethod.GET)public class SchoolController {@AutowiredClassService cs; @GetMapping("/School") public List<Event> School( @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @RequestBody Class class ) throws Exception { List<Class> ClassList = new ArrayList<Class>(); ClassListt = cs.selectClassBySearchCriteria(class.getId(), class.getName(), class.getCreateTime(), class.getUpdateTime());} . 에러내용 Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.util.List<mes.sdc.mads.vo.Event> mes.sdc.mads.controller.DetectionController.anomalyEvent(mes.sdc.mads.vo.Event,org.springframework.ui.Model) throws java.lang.Exception]
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
ORM 책 말인데요..
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]ORM 서적 혹시 개정판 안 나오나요...버전이 꽤나 바뀐 탓에 사고 싶은데 약간 망설여지네요.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
컬렉션의 필요성에 대해 질문 좀 드리겠습니다
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예[질문 내용]먼저 다 대 다 관계라고 하겠습니다.A라는 엔티티와 B라는 엔티티가 다대다로 묶여져 있고 그 중간테이블을 C라고 하겠습니다.이럴 경우에 걍 컬렉션 배치size으로 하는게 아니라 중간 테이블 B로 하면 안되나요?요약하면 강의에서는 페이징이 필요하지 않으면 join fetch로 페이징이 필요하다면 batch size를 활용하라 라고 되어있는데 역으로 @ManyToOne이 있는 다대 일의 다 쪽에서 jon fetch로 모든 것을 해결하면 안되는 건가요?? 아 그리고 질문이 또 있는데 위에서 B에서 A와 C를 fetch join으로 모두 가져오게 설계해도 괜찮죠??
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
default_batch_fetch_size 크기 질문
강의에서default_batch_fetch_size가 100이고,OrderItem의 크기는 2개,Item의 크기는 4개 입니다default_batch_fetch_size를 정할때 OrderItem의 크기와 Item의 크기를 더한 값인가요? 아니면 OrderItem의 크기만 인건가요?
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
JPA> DDD 서로 다른 애그리거트 사이의 간접참조
안녕하세요 영한님! 프로젝트에 JPA 및 DDD를 적용하며 의문점이 생기는 부분이 있는데 물어볼 곳이 마땅치 않아서, 이렇게 질문글 올립니다. 구조(요약) - 모노리틱저희 프로젝트에서 다음과 같이 서로 다른 애그리거트 사이에는 간접참조를 통해 느슨하게 결합하여 사용하고 있습니다. 질문다음과 같이 설정하고 나니 몇 가지 의문점이 있습니다. 간접 참조를 통해 느슨한 결합을 하고 있는데, DB 에 따로 외래키 제약 조건을 걸어주어야하는가? 이 부분에 있어서 팀원과 의견이 달라서요. 저는 애그리거트를 나눈 목적이 결국 복잡도를 줄이기 위해서이고, 각각의 애그리거트 안에서 트랜잭션으로 관리가 되어야한다고 생각을 하는데.. 외래키를 설정하면 결국은 User 를 관리할 때 참조 무결성을 신경쓰면서 Trip 까지 고려를 해야돼서 좋지 않다고 생각합니다. 굳이 DB에서 외래키 제약을 걸지 않아도 이벤트를 통해 관리할 수 있다고 생각을 하기도 하구요. 팀원분은 어플리케이션보다는 변경점이 낮은 DB를 우선으로 하며 개발을 해야하고, 그렇기 때문에 반드시 외래키를 걸어주어야한다고 말씀하시는데, 무엇이 더 맞는 말인지 잘 모르겠습니다. 회원 탈퇴(User 삭제)가 이루어질 때 회원과 관련된 모든 Trip 삭제(벌크성 삭제 쿼리)가 이루어지도록 하기 위해서 이벤트를 활용하고 있는데, 이를 비동기적으로 처리해도 문제가 되지 않는가?@Async, @TransactionalEventListener 를 활용해서 회원탈퇴 요청시 회원 삭제가 커밋이 완료 되면 회원이 작성한 여행 정보를 지우는 비동기 이벤트를 발행하도록 하고 있습니다. 회원 탈퇴시 중요한건 회원 정보를 삭제하는 것이라고 생각해서 이를 비동기적으로 처리하는게 옳다고 생각해서 이렇게 구현했는데, 이 방식이 옳은 방식인지 확신이 서질 않습니다. 현업에서는 어떻게 이런 문제를 해결하고 있는지 궁금합니다! 읽어주셔서 감사합니다!
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
Querydsl 추가 질문입니다
//querydsl 추가 buildscript { dependencies { classpath("gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:1.0.10") } } plugins { id 'org.springframework.boot' version '2.4.1' id 'io.spring.dependency-management' version '1.0.10.RELEASE' id 'java' } group = 'jpabook' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' //apply plugin: 'io.spring.dependency-management' apply plugin: "com.ewerk.gradle.plugins.querydsl" configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-devtools' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5' // implementation 'org.hibernate:hibernate-core:5.4.13.Final' implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.6' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' //추가 testImplementation("org.junit.vintage:junit-vintage-engine") { exclude group: "org.hamcrest", module: "hamcrest-core" } //querydsl 추가 implementation 'com.querydsl:querydsl-jpa' //querydsl 추가 implementation 'com.querydsl:querydsl-apt' } tasks.named('test') { useJUnitPlatform() } //querydsl 추가 //def querydslDir = 'src/main/generated' def querydslDir = "src/main/generated" querydsl { library = "com.querydsl:querydsl-apt" jpa = true querydslSourcesDir = querydslDir } sourceSets { main { java { srcDirs = ['src/main/java', querydslDir] } } } compileQuerydsl{ options.annotationProcessorPath = configurations.querydsl } configurations { querydsl.extendsFrom compileClasspath } //Querydsl 추가, 자동 생성된 Q클래스 gradle clean으로 제거 clean { delete file('src/main/generated') } 이런식으로 build.gradle을 구성했는데요. 어플리케이션을 실행하려고만 하면이런 에러가 발생하면서 실행이 되지 않습니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
처음에 무한루프 부분에서 궁금한게 있어요!
처음에 무한루프 돌때 갑자기 궁금한게 생겨서요.Order -> MemberOrder -> address 위 엔티티들은 둘다 지연로딩인데실제 모든 Order를 조회 했을 때,'지연로딩'이니깐 실질적으로 Member 엔티티를 건드리지 않는 이상은 Member에는 프록시로 담기는 걸로 이해했습니다.그래서 Jackson이 프록시를 건드리지 못해 에러를 발생하는 걸로 이해했구요.근데 동영상에서 6분9초 때에, 포스트맨에서 결과값들이order, member 등등 엔티티들의 값들이 채워져서 보이는데, 지연로딩인데도 값들이 막 보이는게 이해가 안됩니다.정리하자면...모든 Order만 조회했는데, 지연로딩인데도 Member 등 연관된 엔티티들이 다 조회되는 게 이해가 안됩니다혹시 제가 놓친 부분이 있을까요? 지연로딩이 조금 헷갈리고 있는거 같습니다.
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
JPA 트랜잭션과 batch_fetch_size 질문이 있습니다.
@Transactional public List<Order> findAllWithMemberDelivery(int offset,int limit) { List<Order> resultList = em.createQuery( "select o from Order o" + " join fetch o.member m" + " join fetch o.delivery d", Order.class) .setFirstResult(offset) .setMaxResults(limit) .getResultList(); return resultList; } 1. @Transaction이 있을 때 조회쿼리select o1_0.order_id, d1_0.delivery_id, d1_0.city, d1_0.street, d1_0.zipcode, d1_0.status, m1_0.member_id, m1_0.city, m1_0.street, m1_0.zipcode, m1_0.name, o1_0.order_date, o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id join delivery d1_0 on d1_0.delivery_id=o1_0.delivery_id offset ? rows fetch first ? rows only 2023-07-15T01:15:30.105+09:00 TRACE 20476 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [1] as [INTEGER] - [0] 2023-07-15T01:15:30.105+09:00 TRACE 20476 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [2] as [INTEGER] - [100] select o1_0.order_id, o1_0.oder_item_id, o1_0.count, o1_0.item_id, o1_0.order_price from order_item o1_0 where array_contains(?,o1_0.order_id) 2023-07-15T01:15:30.122+09:00 TRACE 20476 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [1] as [ARRAY] - [[1, null, null, null,...] select i1_0.item_id, i1_0.dtype, i1_0.name, i1_0.price, i1_0.stock_quantity, i1_0.artist, i1_0.etc, i1_0.author, i1_0.isbn, i1_0.actor, i1_0.director from item i1_0 where array_contains(?,i1_0.item_id) 2023-07-15T01:15:30.139+09:00 TRACE 20476 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [1] as [ARRAY] - [[2, 1, null, null, null,...] select o1_0.order_id, o1_0.oder_item_id, o1_0.count, o1_0.item_id, o1_0.order_price from order_item o1_0 where array_contains(?,o1_0.order_id) 2023-07-15T01:15:30.142+09:00 TRACE 20476 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [1] as [ARRAY] - [[2, null, ...] select i1_0.item_id, i1_0.dtype, i1_0.name, i1_0.price, i1_0.stock_quantity, i1_0.artist, i1_0.etc, i1_0.author, i1_0.isbn, i1_0.actor, i1_0.director from item i1_0 where array_contains(?,i1_0.item_id) 2023-07-15T01:15:30.144+09:00 TRACE 20476 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [1] as [ARRAY] - [[4, 3, null, null, null,...] public List<Order> findAllWithMemberDelivery(int offset,int limit) { List<Order> resultList = em.createQuery( "select o from Order o" + " join fetch o.member m" + " join fetch o.delivery d", Order.class) .setFirstResult(offset) .setMaxResults(limit) .getResultList(); return resultList; }트랜잭션 없이 실행된 쿼리 select o1_0.order_id, d1_0.delivery_id, d1_0.city, d1_0.street, d1_0.zipcode, d1_0.status, m1_0.member_id, m1_0.city, m1_0.street, m1_0.zipcode, m1_0.name, o1_0.order_date, o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id join delivery d1_0 on d1_0.delivery_id=o1_0.delivery_id offset ? rows fetch first ? rows only 2023-07-15T01:19:19.943+09:00 TRACE 14616 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [1] as [INTEGER] - [0] 2023-07-15T01:19:19.943+09:00 TRACE 14616 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [2] as [INTEGER] - [100] select o1_0.order_id, o1_0.oder_item_id, o1_0.count, o1_0.item_id, o1_0.order_price from order_item o1_0 where array_contains(?,o1_0.order_id) 2023-07-15T01:19:19.957+09:00 TRACE 14616 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [1] as [ARRAY] - [[1, 2, null, null,...] select i1_0.item_id, i1_0.dtype, i1_0.name, i1_0.price, i1_0.stock_quantity, i1_0.artist, i1_0.etc, i1_0.author, i1_0.isbn, i1_0.actor, i1_0.director from item i1_0 where array_contains(?,i1_0.item_id) 2023-07-15T01:19:19.977+09:00 TRACE 14616 --- [nio-8080-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [1] as [ARRAY] - [[2, 1, 4, 3, null, null, null, null, null, null]] @트랜잭션이 있을 때에는 쿼리가 5번 실행이 되고@트랜잭션이 없을 때에는 쿼리가 3번이 실행이 됩니다. 왜 이렇게 동작하는지 생각을 해도 이해가 잘 안되네요