실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
수강정보
(115개의 수강평)
1973명의 수강생
5개월 할부시
월 17,600원88,000원
지식공유자 : 김영한
23회 수업 · 총 6시간 38분 수업
기간 : 평생 무제한 시청
수료증 : 발급 강의
수강 난이도 : 중급이상
cjswoudddn 프로필

페이징을 위한 쿼리 질문드려요! cjswoudddn 1일 전
지난 번 사소한 질문에도 친철히 답변해주시고 알찬 강의 항상 감사드립니다! JPA 최적화 강의를 완강했습니다. 현재 간단한 프로젝트를 진행하고 있는데 페이징에 대해 질문드립니다. DB서버에 select한 데이터의 개수를 지정해서 가져오는 페이징 쿼리를 호출하는 이유로 ' application 메모리에 로드할 수 있는 데이터의 양은 제약이 있기 때문에  한 번의 쿼리로 너무 많은 데이터를 가져올 경우 시스템에 에러가 날 수 있다.' 이렇게 생각했습니다. 질문1) 그럼 시스템이 견딜 수 있는 메모리의 성능을 최대한 고려해서  한 번의 쿼리로 최대한 많은 데이터를 가져오고  최종적으로 모든 데이터를 가져오기 위해 날리는 쿼리의 개수를 최소화하는 게  최적화를 위한 올바른 이해인가요??  질문2) 조금 다른 질문입니다! 만약에 회원가입 시 ID 입력에 대한 요구사항이 1. 100글자를 넘기지 않는다 2. 중복된 ID가 있어서는 안 된다 라고 했을 때 1번 요구사항을 프런트에서 처리했다면 백에서는 1번 요구사항에 대해서는 구현하지 않고 2번 요구사항만 검증하는 식으로  현업에서도 코드를 짜나요?? 항상 너무너무 감사합니다!

1
이지훈 프로필

커맨드와 쿼리 분리 이지훈 2일 전
MemberService의 update 메서드에서 Member를 그대로 반환하지 않는 이유가 커맨드와 쿼리를 분리하기 위해서라고 하셨는데 정확히 이해가 가지 않습니다 ㅠ 1. Member를 update 메서드에서 그대로 반환하면 왜 영속상태가 끊킨 Member가 반환이 되나요? 2.Member를 그대로 반환하면 updateMemberV2 메서드에서 Member member = memberService.update(id, request.getName());return new UpdateMemberResponse(member.getId(), member.getName()); 이런식으로 되면 오히려 강의에서 수정한 Member를 찾는 Select 쿼리 안날라가서 커맨드와 쿼리를 분리할 필요가 없는게 아닌가요..? * 여담으로 스프링 MVC 강의 11월에 출시된다고해서 기다리고있었는데 12월로 미뤄졌네요ㅠㅠ 빨리 듣고싶어요~

2
‍한상진[학생](응용과학대학 응용수학과) 프로필

안녕하세요! ‍한상진[학생](응용과학대학 응용수학과) 3일 전
안녕하세요 강사님  늘 좋은 강의 감사드립니다. 다름아니라 저는 비전공자인데 강사님 강의를 들으면서 따라하고 있는데  저도 프로젝트를 경험해보고 싶은데 어떤 방법이 있을지 알 수 있을까요 ... ? 너무 사소한 질문이지만 답변 부탁드립니다 .. 

1
kd park 프로필

안녕하세요 질문드립니다. kd park 3일 전
안녕하세요. 영한님 덕분에 강의를 시청하고 jpa로 프로젝트를 진행하고있습니다. 현재 "User"객체, "Movie" 객체 그리고 "Score" 객체로 Movie <1 : N>  Score <N : 1> User 이런식으로 유저가 영화에 부여한 평점에 대해  관계를 맺고있습니다. 이제 여기서 평점이 특정 점수 이상인 영화목록을 평점과 함께 가져오려고합니다 select         movie0_.content_id as content_2_5_,         movie0_1_.category as category3_5_,         movie0_1_.description as descript4_5_,         movie0_1_.dtype as dtype1_5_,         movie0_1_.main_title as main_tit5_5_,         movie0_1_.image_id as image_id7_5_,         movie0_1_.production_date as producti6_5_,         movie0_.book_rate as book_rat1_11_,         movie0_.country_code as country_2_11_,         movie0_.netflix_yn as netflix_3_11_,         movie0_.watcha_yn as watcha_y4_11_,         movie0_.origin_title as origin_t5_11_,         movie0_.running_time as running_6_11_,         movie0_.total_audience as total_au7_11_      from         movie movie0_      inner join         content movie0_1_              on movie0_.content_id=movie0_1_.content_id      where         (             select                 avg(score1_.score)              from                 score score1_              where                 movie0_.content_id=score1_.content_id         )>=4.0 limit ? 대충 이런 쿼리로 생각하고있습니다. 근데 점수(score)를 중간 테이블로 분리하다보니 이걸 dto에 맵핑하는 과정에 좀 고민되는 부분이 있습니다. Movie 엔티티에 averageScore라는 컬럼을 넣을순없으니 이걸 어떻게 해야하나 싶은데 1.  jpql로 순수한 Movie엔티티를 먼저조회하고 그 정보를 가지고 영화들의 평균점수를 조회한뒤 합친다. 이렇게하면 영화조회할때 avg(score) 비교연산 하는부분의 서브쿼리를 평균점수 조회때 한번 더 돌려야합니다. 그리고 가져온뒤 pk값으로 맵핑을 일일이해줘야하는데 jpa가 해야할일을 제가하는 느낌입니다. 2. jpql로 애초에 DTO로 맵핑하게끔해서 한번의 조회로 끝낸다. 근데 뭔가 jpql에서 바로 DTO로 조회하는게 탐탁치않습니다. 3. 네이티브쿼리를 쓴다. 제일 간단한 방법인데 사실상 2번 방법이랑 비슷한거 같네요. 어떤게 가장 jpa스러운 해결방법인지, 사실 위에 3개다 별로인거같아서 여쭤봅니다. 감사합니다.

1
신용선 프로필

querydsl gradle 추가 오류.. 신용선 9일 전
compileQuerydsl 더블클릭하면 아래처럼 나오고 generated 폴더가 생기질 않습니다. 어떻게  하나요.. //querydsl 추가buildscript { dependencies { classpath("gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:1.0.10") }}plugins { id 'org.springframework.boot' version '2.3.4.RELEASE' id 'io.spring.dependency-management' version '1.0.10.RELEASE' id 'java'}apply plugin: "com.ewerk.gradle.plugins.querydsl"group = 'jpabook'version = '0.0.1-SNAPSHOT'sourceCompatibility = '11'configurations { compileOnly { extendsFrom annotationProcessor }}repositories { mavenCentral()}dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 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.github.gavlyukovskiy:p6spy-spring-boot-starter:1.6.2' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } //querydsl 추가 implementation 'com.querydsl:querydsl-jpa' //querydsl 추가 implementation 'com.querydsl:querydsl-apt'}test { useJUnitPlatform()}//querydsl 추가//def querydslDir = 'src/main/generated'def querydslDir = "$buildDir/generated/querydsl"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}

3
아슈레이 프로필

ArrayJson의 dto 관련 아슈레이 15일 전
안녕하세요! 이번에 처음으로 jpa를 사용해서 토이프로젝트를 하고있습니다. 질문에 앞서서 이런 강의 만들어주셔서 너무 감사합니다 한눈에 쏙들어오고 이해가 됩니다 ㅎㅎ 제가 드릴 질문은  json방식이 Array방식일경우 dto에 자동으로 맵핑이 안되더라구요...어떤방식으로 해야자동맵핑이 될지 궁굼합니다.

1
안지혁 프로필

주문내역.. 안지혁 16일 전
안녕하세요? 강사님.. 여쭤볼게있습니다.  주문내역의 대표상품이 아닌 각각의 리스트를 뽑아보고 싶은데요.. 제가 생각한 쿼리는 select * from orders o inner join member m on o.member_id = m.member_id inner join order_item oi on o.order_id = oi.order_id; 결과는 이렇습니다. mybatis같은것에 익숙해서 이런식으로 vo를 만들어서 출력하곤했지만 jpql은 아직 많이 헷갈리네요.ㅠㅠ 일단 생각한 jpql은 아래와 같습니다. select o from Order o join o.member m join o.orderItems as oi 이렇게 하여  List<Order>  로 뽑아서 타임리프에 출력시 다중반복으로 출력을 면될거 같은데 출력이 아래 처럼 잘못  나오고있네요;;  감이 잘 오지 않는데  jpql을 제가 잘못 생각한것이지 어디가 잘못된건지 조언 좀 해주세요..  역시 설명을 들으면 고개가 끄덕여지지만 직접해보면 갸우뚱 거리네요..ㅠㅠ;

1
두잇베스트 프로필

강사님 에러 질문입니다. ㅠㅠ 두잇베스트 17일 전
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2020-11-17 16:24:19.845 ERROR 34406 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'initDb': Invocation of init method failed; nested exception is java.lang.NullPointerException at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:139) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:413) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1761) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:514) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:321) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:319) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:863) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.1.16.RELEASE.jar:2.1.16.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744) [spring-boot-2.1.16.RELEASE.jar:2.1.16.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391) [spring-boot-2.1.16.RELEASE.jar:2.1.16.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) [spring-boot-2.1.16.RELEASE.jar:2.1.16.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.1.16.RELEASE.jar:2.1.16.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1204) [spring-boot-2.1.16.RELEASE.jar:2.1.16.RELEASE] at jpabook.jpashop.JpashopApplication.main(JpashopApplication.java:10) [classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.1.16.RELEASE.jar:2.1.16.RELEASE] Caused by: java.lang.NullPointerException: null at jpabook.jpashop.initDb$InitService.dbInit1(initDb.java:43) ~[classes/:na] at jpabook.jpashop.initDb$InitService$$FastClassBySpringCGLIB$$2eb0016.invoke(<generated>) ~[classes/:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:752) ~[spring-aop-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) ~[spring-tx-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) ~[spring-aop-5.1.17.RELEASE.jar:5.1.17.RELEASE] at jpabook.jpashop.initDb$InitService$$EnhancerBySpringCGLIB$$a95ed200.dbInit1(<generated>) ~[classes/:na] at jpabook.jpashop.initDb.init(initDb.java:29) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:363) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:307) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136) ~[spring-beans-5.1.17.RELEASE.jar:5.1.17.RELEASE] ... 23 common frames omitted package jpabook.jpashop; import jpabook.jpashop.domain.*; import jpabook.jpashop.domain.Item.Book; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; import javax.persistence.EntityManager; // 총 주문 2 //-userA // JPA1 BOOK // JPA2 BOOK //-userB // SPRING1 BOOK // SPRING2 BOOK @Component @RequiredArgsConstructor public class initDb { private final InitService initService; @PostConstruct public void init() { initService.dbInit1(); } @Component @Transactional @RequiredArgsConstructor static class InitService { private EntityManager em; public void dbInit1() { Member member = new Member(); member.setName("userA"); member.setAddress(new Address("서울","1", "1111")); em.persist(member); Book book1 = new Book(); book1.setName("JPA1 BOOK"); book1.setPrice(10000); book1.setStockQuantity(100); em.persist(book1); Book book2 = new Book(); book2.setName("JPA2 BOOK"); book2.setPrice(20000); book2.setStockQuantity(100); em.persist(book2); OrderItem orderItem1 = OrderItem.createOrderItem(book1, 10000, 1); OrderItem orderItem2 = OrderItem.createOrderItem(book2, 20000, 2); Delivery delivery = new Delivery(); delivery.setAddress(member.getAddress()); Order order = Order.createOrder(member, delivery, orderItem1, orderItem2); em.persist(order); } } } 아마도 initDb 빈 생성에서 에러가 나는거 같은데 왜 그런지 모르겠습니다. 

3
갓다귀갓장국 프로필

영상 11:00 ~ 11:30 내용 질문입니다. 갓다귀갓장국 20일 전
OrderRepository에 직접 접근해서 findAll을 호출해서 DTO 객체를 만드는데요. 이메서드에는 @Transactional이 안붙어있어서 엔티티매니저가 메서드 호출이 완료되더라도 1차캐시가 끝나지않고 유지되는데 문제는  @Transactional를 붙일경우 메서드 호출이 끝나면 엔티티 매니저도 같이 종료시켜버리지만, 이 코드에서는 컨트롤러에서 엔티티 매니저를 close()를 명시적으로 호출하지 않는데 이럴경우 문제 없을까요? 

1
손준수 프로필

엔티티 < -> DTO 관련 해서 조언을 듣고싶습니다. 손준수 23일 전
안녕하세요.  엔티티와 DTO 변환 관련으로 한가지 조언을 듣고 싶어서 글 남깁니다. 저흰 mapstruct를 이용해서 DTO<->엔티티 변환을 자동화 하고 있고 그래서 대부분의 DTO가 엔티티와 변수명과 구조가 일치하고 필요하지 않은 정보는 제거하는 식입니다. 강의를 예로 들면 OrderDto에 name이 바로 있는게 아니라 Member객체로 래핑되어 있는 식이죠.  변환과정을 자동화해서 개발공수를 줄이는게 목적이었고 한 솔루션 내에서 프론트와 백앤드를 api 통신으로 연동하는 구조기 때문에 api spec를 고치는건 크게 문제가 안되기 때문에 이런 방식을 채택했습니다.  앞으로도 이런방식을 하는게 좋을지 아니면 강의에 나온거처럼 변환을 수동으로 해서  엔티티 spec 변경 시에도 응답값을 고정하는게 좋을지 조언을 듣고싶습니다. 감사합니다.

1
kd park 프로필

안녕하세요 질문이있습니다. kd park 29일 전
안녕하세요 김영한님 다름이 아니라 jpa 사용하면서 생긴 궁금증때문에 글을 남겨봅니다. 현재 Order를 추가로 생성하기 위해 API 에서 memberId, itemId를 받아와서 Member 조회 (select 1번) Item 조회 (select 1번) Order에 Set 후 추가 (insert 1번) 이런 식으로 되는 것 같은데요. 이렇게 insert 1번을 위해 select를 2번 날리는 방법이 일반적인 방법인가요? 테이블이 복잡하고 외래키 관계가 많아지면 사전 select가 3~4번 이상도 나갈 수 있을 것 같은데 이럴땐 일반 날쿼리를 써야하나 고민이 됩니다. 실무에서는 그냥 감수하고 select 날려서 쓰는지 궁금합니다. 한가지 질문이 더 있습니다. 만약 게시판에 댓글을 추가할 때 board.getComments.add(comment); 이런식으로 insert 한다고 치면 이것도 결국 불필요한 select가 나가야 하고 (LazyLoading 발동하면) 혹여나 그 select의 결과가 수백 수천개라면 (댓글이 수백 수천) 문제가 될 것 같고 사실 많은 경우는 자식 엔티티 갯수가 적다는게 보장되지 않는 경우일텐데 일반적으로 저렇게 add 하는 경우가 실무에서 잦은가요? 아니면 대부분은 그냥 comment.setBoard(board)해서 넣는 방식인가요? 감사합니다.

2
kangsy763 프로필

트랜잭션에 대해 질문이 있습니다. kangsy763 1달 전
안녕하세요 영한님, 해당 질문을 어디에 작성해야할지 몰라서 여기다가 남겨봅니다! 자바 ORM 표준 JPA 프로그래밍 책을 보다가 궁금점이 생겨서 질문남깁니다. P.580을 보면 logic() 메서드 위에 @Transactional 이 붙어있고 설명으로 메서드를 호출할 때에 트랜잭션을 먼저 시작하고 서비스가 끝나면 트랜잭션이 종료되었다고 설명되어있습니다. p.579 의 2번째 문단에서 또한 메서드와 엮어서 설명을 하고있습니다. 그렇다면, 클래스 위에 @Transactional를 붙여주었을 경우에는 해당 클래스가 호출될 때에 트랜잭션이 시작되게 되는 것인가요? 아니면 메서드 별로 다 붙게되는 것인가요? 만약 전자라면 트랜잭션의 종료 시점은 애플리케이션의 종료시점이 되는 것인지 궁금합니다.

1
m s 프로필

EntityMager를 어떤식으로 넣어주는건가요? m s 1달 전
안녕하세요! 여기서 EntityMager를 @Autowired할때 스프링 컨텍스트에서 매번 EntityMager를 생성하고 빈으로 등록해서 자동으로 주입시켜주는건가요?? (EntityMager는 공유되면 안되는 객체이므로 매번 생성하는걸로 이해했습니다.) 추가적으로 @DataJpaTest를 통해 테스트를 할때 @Entity 어노테이션과 @Repository 어노테이션이 붙은 클래스만 빈으로 등록되는걸로 알고 있습니다. 그러면 이때 EntityMager는 빈으로 등록되지도 않는데 어떻게 주입되는걸까요?

1
정윤성 프로필

Spring Data JPA에서 Page쿼리 작성도중 page의 size가 의도된 수넘어가면 타입에러가뜹니다 ㅠㅠ 정윤성 1달 전
실제 Comment도메인와 Query부분 로직입니다 문제는 Pageable의 size가 10이라고쳤을때 entity의 개수가 10개미만일경우는 에러가 발생하지않지만 딱 size개수 혹은 그이상이 될경우 페이지가 분리가 되지않고 위와같은 타입변환에러가 출력되었습니다 ( pageable의 size를 늘려줄경우 잘 작동합니다 페이지가 분리만 안되는거같아요 ) 이유를 잘모르겠어서 querydsl 로도 똑같이 작성해봤는데 이는 잘 작동하였습니다 혹시 이부분에 대해서 아시는게 있는지 여쭈어 보고싶습니다 ㅠㅠ 정리 : Spring Data JPA에서 entity의 개수가 size를 넘어갈경우 페이지가 넘어가지지않고 타입변환에러가 발생 ! ( 이전에는 공부할때 이런경험이 없었습니다 ) * 그리고 페치조인이아니라 일반 join을 할경우 entity의 기본생성자가 private타입이면 안되는건가요 ??

2
Jaeik Lee 프로필

OneToMany 단방향 관련해서 궁금합니다. Jaeik Lee 1달 전
안녕하세요. 좋은 강의 제공해주셔서 감사드립니다. OneToMany 단방향의 경우, 불필요한 insert, update가 발생할 수 있기 때문에 지양하는 방법이라 알고있는데요. @JoinColumn을 사용하여 insertable, updatable 값을 false로 설정하면, 위의 단점을 해결할 수 있을거 같은데요. 혹시 이외에 추가로 OneToMany의 단방향을 지양해야하는 이유가 있는지 궁금합니다!

1
지식공유자 되기
많은 사람들에게 배움의 기회를 주고,
경제적 보상을 받아보세요.
지식공유참여
기업 교육을 위한 인프런
“인프런 비즈니스” 를 통해 모든 팀원이 인프런의 강의들을
자유롭게 학습하는 환경을 제공하세요.
인프런 비즈니스