월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결실전! 스프링 데이터 JPA
강의 15분경 즉시로딩 실행결과 질문입니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.MemberTest 테스트클래스testEntity() 코드입니다. Team teamA = new Team("teamA"); Team teamB = new Team("teamB"); em.persist(teamA); em.persist(teamB); Member member1 = new Member("member1", 10, teamA); Member member2 = new Member("member2", 20, teamA); Member member3 = new Member("member3", 30, teamB); Member member4 = new Member("member4", 40, teamB); em.persist(member1); em.persist(member2); em.persist(member3); em.persist(member4); //초기화 em.flush(); em.clear(); List<Member> members = em.createQuery("select m from Member m ", Member.class) .getResultList(); for (Member member : members) { System.out.println("member = " + member); System.out.println("-> member.team = " + member.getTeam()); }처음에 즉시로딩 실행결과로멤버 조회 쿼리 하나랑각각 팀 조회 쿼리 +N번 (여기서는 2번) 나가는 것을 확인했습니다. 지연로딩으로도 쿼리실행시점 문제만 다르지 똑같이 member.getTeam() 할때 team쿼리가 나가는 것을 확인했습니다. N+1문제를 해결하기 위해 페치조인을 한다는것은 강의와 학습을 통해 알게되었습니다. 질문이있는데요처음에 즉시로딩할때 조인쿼리가 안나가고왜 따로 member, team쿼리가 나간것일까요? 즉시로딩도 N+1문제가 발생하는것이 맞나요? 수정단건조회 시 즉시로딩으로 left outer join 으로 member와 team이 함께 조회되는것을 확인했습니다.단건조회가 아니라 memberRepository.findAll() 메소드나 JPQL (select m from Member m) 인경우에는 member와 team이 같은 한 쿼리가 아니라따로 조회되는 것인가요? 왜 List를 조회할때에는 같이 join해서 쿼리를 날리지않는것일까요?
- 미해결실전! 스프링 데이터 JPA
NullPointerException발생 이유를 모르겠습니다
테스트 코드를 작성하였는데, NullPointerException이 발생합니다 ..
- 미해결실전! 스프링 데이터 JPA
QueryHint readonly 와 영속성 컨텍스트 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]MemberRepository /** * JPA Hint */ @QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true")) Member findReadOnlyByUsername(String username); test @Test @Rollback(false) void findReadOnlyByUsername() { // given memberRepository.save(new Member("member1", 10)); em.flush(); em.clear(); // when Member member = memberRepository.findReadOnlyByUsername("member1"); // 쿼리힌트로 readonly 설정 member.setUsername("member2"); em.flush(); // update 쿼리가 나가지 않음 em.clear(); System.out.println("member.getUsername() = " + member.getUsername()); }영한님이 설명해주신대로 update 쿼리가 나가지 않아서 실제 DB 상에는 member2 가 아닌 member1 이 들어가있음을 확인했습니다그리고 em.clear() 로 영속성컨텍스트를 초기화 한 후, member 의 username 을 찍어봤는데 member2 가 찍히더라구요저는 영속성 컨텍스트를 초기화했으므로, member 조회 시 DB 에서 가져오므로 member1 이 찍힐 것이라고 생각했는데 제 생각이 틀린 건가요? 아래는 출력로그 입니다 2023-08-14 17:17:17.797 INFO 15063 --- [ main] p6spy : 23.08.14 17:17:17 | OperationTime 4 ms | statement | connection 3 select member0_.member_id as member_i1_0_, member0_.age as age2_0_, member0_.team_id as team_id4_0_, member0_.username as username3_0_ from member member0_ where member0_.username='member1' member.getUsername() = member2
- 해결됨실전! 스프링 데이터 JPA
Slice 방식에서의 엔티티를 DTO 로 변환
Page 방식에서 api response 를 줄 때 엔티티-> DTO 변환은 Page 인터페이스에서 지원하는 map 을 이용하는 것이라고 이해했습니다.Slice 인터페이스의 스펙에는 map 함수가 없던데 Slice 를 사용할 때 엔티티-> DTO 변환은 어떻게 해야 하나요?
- 해결됨실전! 스프링 데이터 JPA
1:N 양방향 매핑시에 컬렉션 필드 초기화가 안되는 문제..
안녕하세요. 강의 코드를 참고하며 1:N 양방향 매핑을 시도하고 있습니다.다른 테이블에서는 성공적으로 해서 정말 다른거 없이 똑같이 매핑해서 테스트를 진행중이었는데정말 이유를 모르겠는게 객체가 생성되면서 멤버 변수가 초기화가 되어야 하는데 되지 않아 null값이 들어가있고.null 값이 들어간 List에 add를 하려고 하니 NullPointerException이 나고 있습니다.같은 로직, 같은 OneToMany 매핑을 한 다른 엔티티 에서는 잘 되었는데 해당 부분에서 어떤 이유로 생성될때 멤버변수가 초기화가 되지 않는지 도무지 잘 모르겠습니다.. 이유를 아시는분 도와주시면 정말 감사하겠습니다.정상적으로 진행된 매핑 및 코드는 아래와 같습니다.@Entity @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorColumn(name = "dtype") @DiscriminatorValue("my") @Table(name="my_wallets") @Getter @Setter public class MyWallet { @Id @GeneratedValue @Column(name = "wallet_id") private Long id; private Integer balance=0; //cascade = Persist 속성을 명시해줌으로써, 영속성 전이를 사용하였음. //orphanRemoval = true 를 사용해서 고아 객체를 자동으로 제거 함. @OneToMany(mappedBy = "wallet", cascade = CascadeType.PERSIST,orphanRemoval = true) private List<Transactions> transactions = new ArrayList<>(); public void addTransactions(Transactions transaction){ this.transactions.add(transaction); transaction.setWallet(this); } ------------------------------------- @Entity @Table(name = "transactions") @Getter @Setter @ToString @AllArgsConstructor @NoArgsConstructor @Builder public class Transactions { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "transaction_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "wallet_id") @Setter private MyWallet wallet; private Long counterId; private Timestamp transactionDate; private String transactionType; private Integer amount; private String location; private Integer balance; private Boolean success; } ----------------------테스트 부분 Transactions t = Transactions.builder() .amount(100) .balance(200) .success(Boolean.TRUE) .build(); MyWallet m1 = createMyWallet(); m1.addTransactions(t); em.persist(m1);컴파일 에러도 없고, 정상적으로 h2 db에 들어가는것을 확인 했습니다.그런데 같은 로직으로 진행한 연관관계 메서드에서 오류가 발생했습니다.문제가 되는 코드들은 아래와 같습니다. import lombok.*; import javax.persistence.*; import java.util.ArrayList; import java.util.List; @Entity @Table(name = "article") @Getter @Setter @ToString @AllArgsConstructor @NoArgsConstructor @Builder public class Article { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "article_id") private Long id; private Long walletId; private Long imageId; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "transaction_id") private Transactions transaction; @OneToMany(mappedBy = "article",cascade = CascadeType.PERSIST, orphanRemoval = true) private List<Comments> comments = new ArrayList<>(); // List<Commnets> comments = new ArrayList 를 해주었음에도 null이 들어가있음. public void addComment(Comments comment){ //따라서 null 에 add 를 하려고 하니 NullPointerException이 발생합니다.. comments.add(comment); comment.setArticle(this); } } import lombok.*; import javax.persistence.*; import java.sql.Timestamp; @Entity @Table(name = "comments") @Getter @ToString @AllArgsConstructor @NoArgsConstructor @Builder @Setter public class Comments { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "comment_id") private Long commentId; @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "article_id") @Setter private Article article; private Long writerId; private String content; private Timestamp postedDate; } 이 아래는 실행해봤던 테스트 코드중 발생하는 위치의 코드입니다.. Article article = Article.builder() .imageId(99L) .walletId(1L) .imageId(-99L) .build(); em.persist(article); Comments comment = Comments.builder().content("컨텐츠1").writerId(123L).build(); System.out.println("comment = " + comment.toString()); em.persist(comment); article.addComment(comment); //이 부분이 문제..persist를 안해줘서 그런가 싶어서 앞뒤로 옮기며 확인해봤는데 여전히 필드 초기화가 되지 않아서 정말 의문입니다 제가 기본적으로 무엇을 놓치고 있는걸까요 ㅠㅠ 테스트 코드에서 무언가 잘못했을까 싶어 전체 코드도 남겨봅니다. import lombok.RequiredArgsConstructor; import org.apache.tomcat.jni.Address; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; import javax.persistence.EntityManager; import java.awt.print.Book; @Component @RequiredArgsConstructor public class initDb { private final InitService initService; @PostConstruct public void init() { initService.doInit1(); // initService.doInit2(); } @Component @Transactional @RequiredArgsConstructor static class InitService { private final EntityManager em; public void doInit1() { Transactions t = Transactions.builder() .amount(100) .balance(200) .success(Boolean.TRUE) .build(); MyWallet m1 = createMyWallet(); m1.addTransactions(t); em.persist(m1); MoimWallet moim = createMoimWallet(1000); em.persist(moim); System.out.println("2차 테스트"); moim.setBalance(100); //Mywallet으로 업 캐스팅 ok MyWallet moim2 = createMoimWallet(2000); em.persist(moim2); User user = new User(null, m1, 1L, "ansik_id", "1234", "안식_name", "981212-121212", "010111", UserType.Parent, null); // user.getUsername("안식씨"); em.persist(user); WalletsAndMember wam = new WalletsAndMember(null, moim, user); em.persist(wam); WalletsAndMember wam2 = new WalletsAndMember(null, (MoimWallet) moim2, user); em.persist(wam2); Article article = Article.builder() .imageId(99L) .walletId(1L) .imageId(-99L) .build(); em.persist(article); Comments comment = Comments.builder().content("컨텐츠1").writerId(123L).build(); System.out.println("comment = " + comment.toString()); em.persist(comment); System.out.println("comment = " + comment.toString()); // comment.setArticle(article); article.addComment(comment); // article.getComments().add(comment); em.persist(article); em.flush(); em.clear(); } private static MyWallet createMyWallet() { MyWallet myWallet = new MyWallet(); return myWallet; } private static MoimWallet createMoimWallet(int amount) { MoimWallet moimWallet = new MoimWallet(); moimWallet.setTarget_amount(amount); return moimWallet; } } } 아래에 에러 로그를 남겨봅니다Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2023-08-10 00:59:32.985 ERROR 47056 --- [ 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:160) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:440) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:920) ~[spring-context-5.3.28.jar:5.3.28] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.28.jar:5.3.28] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.13.jar:2.7.13] at team.ServerApplication.main(ServerApplication.java:12) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-2.7.13.jar:2.7.13] Caused by: java.lang.NullPointerException: null at team.entities.Article.addComment(Article.java:33) ~[classes/:na] at team.initDb$InitService.doInit1(initDb.java:74) ~[classes/:na] at team.initDb$InitService$$FastClassBySpringCGLIB$$48d5c178.invoke(<generated>) ~[classes/:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.28.jar:5.3.28] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.28.jar:5.3.28] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.28.jar:5.3.28] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.28.jar:5.3.28] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.28.jar:5.3.28] at team.initDb$InitService$$EnhancerBySpringCGLIB$$3cdef9a7.doInit1(<generated>) ~[classes/:na] at team.initDb.init(initDb.java:22) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ~[spring-beans-5.3.28.jar:5.3.28] ... 23 common frames omitted Process finished with exit code 1
- 미해결실전! 스프링 데이터 JPA
연관관계없이 테이블 설계 및 JPA Domain Class 작성 문의
안녕하세요. 현재 김영한님의 JPA관련 강의들을 수강하면서 기존 프로젝트에서 JPA 로 변경시 문제가 있어 문의드립니다.배운 것을 실적용할 경우 문제는, 테이블 설계시 제약사항이 테이블 간 연관관계 설정을 하지 않는 것입니다.이 경우 도메인클래스를 어떻게 작성해야 할지 적절한 기준과 방법을 몰라 문의드립니다.간략히 예를들어 DBA권고에 따라 외래키 설정은 모두 하지 않는다고 가정해서 아래와 같이 테이블을 생성했을 시에| COMMENT | | COMMENT_IMAGE | | comment_id(PK)| | comment_img_id(PK)| | user_name(PK) | ------- X ------ | comment_img_name | | comment_id | /* DO NOT USE CONSTRAINT foreign key() references */따라서 기존에 아래와 같은 DTO가 있다면,public class Comment { .... private Long id; private String name; private List<CommentImage> commentImages; .... }로 작성되어 있을 경우 아래와 같이 수정중인데... @IdClass(CommentId.class) public class Comment { .... @Id private Long id; @Id private String name; //@? private List<CommentImage> commentImages; .... }기존에는 따로 CommentImage List<>를 조회해서 넣어주면 됐지만cmt = DAO.getComment(id, name); cmt.setCommentImages( DAO.getCommentImageList( cmt.getId() ) ); return cmt; /* getComment SQL SELECT * FROM COMMENT WHERE COMMENT_ID = :id AND USER_NAME = :name; getCommentImageList SQL SELECT * FROM COMMENT_IMAGE WHERE COMMENT_ID = :comment_id; */ JPA의 경우 Domain 클래스에서 Join관련 어노테이션 설정이 없으면 Could not determine recommended JdbcType 오류가 발생합니다. 이 경우 연관관계 생성없이 도메인을 설계하고 사용하는 방법을 알 수 있을까요?
- 미해결실전! 스프링 데이터 JPA
안녕하세요
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]안녕하세요 성능 테스트를 해보고 QueryHint 를 적용할지 고민하라고 하셨는데 성능 테스트란 정확하게 어떤 걸 의미하나요? 부하 테스트 인지 맞다면 예시가 뭐인지 궁금합니다.그리고 성능 테스트를 하면 QueryHint 를 쓰는게 더 성능이 좋게 나올텐데 그럼 쓰는 게 낫지 않나 하는 궁금증이 듭니다.
- 미해결실전! 스프링 데이터 JPA
long 반환타입
MemberJpaRepository의 count 함수에서 Long이 아닌 long 으로 반환타입을 작성 하는 이유가 뭔가요?Long으로 해도 상관 없는걸까요?
- 미해결실전! 스프링 데이터 JPA
@CreatedDate에 관하여
@CreatedDate가 persist 전에 호출된다는 말씀이 -> persist 전에 호출되기 때문에 createdDate의 값을 가져오기 위해 별도의 쿼리를 날리지 않는다는 말인가요??또 CreateDate를 사용하는 이유가 persist 전에 호출되고 persist 이후에 JPA가 createdDate에 값을 넣어주기 때문에 사용한다고 생각하는게 맞을까요??
- 미해결실전! 스프링 데이터 JPA
DTO 조회하기 n+1오류
강의 내용은 간단하게 설명해주셧는데1.OneToMany의 경우나 n+1문제가 발생할 경우는 어떻게 해결하나요?2.강의에서는 join만 썻는데 fetch join은 불가능한가요?
- 해결됨실전! 스프링 데이터 JPA
기초적인 질문입니다...
public void changeTeam(Team team) { this.team = team; team.getMembers().add(this);}강의를 들었을 때 양방향 연관관계에서는 한쪽에만 작업을 해주면 안되고 양쪽을 작업해줘야 하기 때문에 위와 같은 코드를 작성한다고 알고 있습니다.위 코드에서 팀 변경으로 인해 새로운 팀에 member를 추가해주고 기존의 팀의 list에서 제거해주는 작업은 별도로 진행하지 않아도 되는지 궁금하여 질문 남깁니다...한쪽에 설정해주면 JPA가 알아서 양방향 연관관계에 대해서 정리해주는건가 싶기도 하고 잘모르겠어서 질문 드립니다
- 미해결실전! 스프링 데이터 JPA
JOIN 관련해서 질문드릴게 있어요!
안녕하세요. 수업 듣다가 갑자기헷갈려서 여쭤볼게 생겼어요.@Query("select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) " + "from Member m join m.team t")위 같은 쿼리에서 Member entity에 t.name이란게 없으니 저는 fetch join을 써야 한다고 처음에 생각했거든요.일반 join은 조회시 join 대상이 되는 entity는 조회 대상이 되는 칼럼에서 불러지지 않고, 불러진다면, 따로 쿼리가 동작하기 떄문에 N+1 이 발생하는 걸로 알고있었는데, 수업에서 log보니깐 select 쿼리에서 t.name 도 같이 한 쿼리에 조회되는게 보여서 갑자기.. 멍해지더라구요 ㅋㅋ;;;저는 member 따로 1번, team따로 1번 돌거라고 예상했었는데... 제가 놓친 부분이 있을까요?? 답변 미리 감사드리겠습니다.
- 해결됨실전! 스프링 데이터 JPA
isNew() 메서드의 구현체 문의
안녕하세요! isNew() 메서드의 구현체가 정확히 무엇인지 확인하고 싶어 질문드립니다!SimpleJpaRepository의 save() 메서드 내부에서 isNew() 메서드가 호출될 때,if (entityInformation.isNew(entity)) {처럼 호출되는데요, 이 때 isNew 가 org.springframework.data.repository.core.EntityInformation 인터페이스의 추상 메서드인 것을 확인했습니다.그런데 이 isNew 의 구현체가 여러개라서 하나씩 확인해보니 강의에서 설명해주신 내용이 추상 클래스 org.springframework.data.repository.core.support.AbstractEntityInformation 에 구현된 내용과 같더라고요.// AbstractEntityInformation.isNew() public boolean isNew(T entity) { ID id = getId(entity); Class<ID> idType = getIdType(); if (!idType.isPrimitive()) { return id == null; } if (id instanceof Number) { return ((Number) id).longValue() == 0L; } throw new IllegalArgumentException(String.format("Unsupported primitive id type %s", idType)); }그런데 AbstractEntityInformation 역시 추상 클래스이다 보니 정확한 구현체를 찾기가 힘든 상태입니다. 질문) SimpleJpaRepository의 save() 내부에서 사용되는 isNew() 의 구현체는 정확히 어떤 클래스인가요? 또, 이러한 구현체가 정확히 무엇인지 알 수 있는 방법이 있을까요?확인해주셔서 감사합니다. :D
- 미해결실전! 스프링 데이터 JPA
loginfailureHandler에서 db에 로그 저장 시 에러
안녕하세요질문이 있어서 글을 남깁니다. 로그인 실패 시 handler에서 DB에 로그를 남기고 싶은데,마지막 loginLogService.saveLoginLog(loginLogDto); 에서 null 됩니다.어떤 것이 문제일까요???답변 부탁드립니다.감사합니다.
- 미해결실전! 스프링 데이터 JPA
빌더와 생성자의 보안 차이가 궁금합니다!
setter를 지양하는 이유 중에 하나가 보안성이라고 생각했습니다.그런데 builder를 사용하면 똑같이 보안에 문제가 생기지 않나 의문이 들었습니다.값을 변경하거나 삽입할 때 함수를 따로 만드는 것이 가장 보안성이 좋지만 파라미터가 많을 때 가독성과 편리성을 위해 builder를 사용하는 건가요??
- 미해결실전! 스프링 데이터 JPA
모든 쿼리에 같은 where조건이 필요 할 때
예시 상황은 여러 학생이 테이블을 공유해서 사용하여 모든 테이블에 student_id 컬럼이 있고 이를 이용해 데이터 사용자를 구별한다고 했을 때입니다.이럴 때 모든 find, update, delete 절에 where student_id = '1000' 와 같은 조건이 필요하다고 하면 단순히 모든 find문에 findByStudentId 하고 아이디를 넣어주는 수밖에 없을까요?어플리케이션 사용자 학생 아이디는 properties에 적어놓고 가져와 사용할 것이라 프로세스 실행중에 파라미터로 받아오는 경우는 없습니다.
- 미해결실전! 스프링 데이터 JPA
단방향 연관관계 적용시 질문 있습니다.
일반적으로 양방향 연관관계는 지양하는 것이 좋다고 해서, 단방향 연관관계로 생각을 해보고 있는데요. Member (N) 쪽에만 Team 쪽으로 단방향 연관관계를 설정한 상태인데요. 특정 팀의 멤버들을 알고 싶은 경우가 있을거 같아요. Member 중, team id 가 X 인 것을 찾고 싶은 경우에는 어떻게 해야하나요? fetch join 시에는 별칭을 줄 수 없기 때문에 안될거 같습니다. 이럴때는 그냥 일반 조인문으로 풀어내고, team 정보가 필요하다면 다시 조회하는 것이 맞나요?
- 미해결실전! 스프링 데이터 JPA
data jpa 사용 시 쿼리도 aop 같은 방식이 적용 가능한가요?
안녕하세요. 강의 듣고, jpa이용해서 팀 프로젝트 만들어 보고 있습니다.다름이 아니라, 게시글 삭제 시, 정말 게시글이 삭제되는 것이 아니라, 게시글 안의 Enum 에 deleted로 변경 해 두고, 일정 시간이 삭제되게 하려고 했습니다.변경 까지는 문제가 없었는데, 이렇게 기능이 추가가 되니, 기존에 게시 글을 반환하던 쿼리 들에 전부where status = 'ACTIVE' 와 같은 조건을 넣어주어야 하게 되었습니다. 전부 수작업으로.... 조건을 넣어주는 방법 밖에는 없을까요? 간단한 프로젝트라고 생각해서 QueryDsl은 사용하지 않았습니다.또 저 조건을 개발자가 전부 쿼리 개발 할 때 필수로 넣어야 된다면, 어쩌다 까먹고 안 넣게되면 삭제 처리 되었던 게시글이 사용자 눈에 보이는..참사가 발생할 것 같습니다.기존 Repository 쿼리가 실행되기 전에 먼저 article.status = 'ACTIVE' 인 것들만 필터를 하고, 거기에 제가 지금까지 만들어 놓은 쿼리들이 적용이 되면 될 것 같은데, 아무리 찾아봐도 좋은 대안이 보이지가 않아 보여서 혹시나 하는 마음에 질문 드립니다.감사합니다.
- 미해결실전! 스프링 데이터 JPA
벌크연산이 영속성 컨텍스트를 무시하는 이유
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용]안녕하세요 선생님 좋은 강의 감사합니다.벌크연산이 영속성 컨텍스트를 무시하고 곧바로 db에 반영되는 이유가 메모리 크기의 한계 때문일까요? 이렇게 설계된 이유가 궁금합니다!
- 미해결실전! 스프링 데이터 JPA
pathVariable관련 질문 드립니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)네 조금은 다를수있습니다.2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)네3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)네[질문 내용]강의와는 조금 다를수있지만/mebers/{id} 이렇게 조회를 하면 누군가도 똑같은 url을 입력하여 해당 정보를 볼수 있다고 생각하는데 이런거에 대한 위험성같은거는 따로 처리하는 방법?같은게 있는지 궁금합니다.