형 질문있어. 페이징 기반 ItemReader 에서는 예제와 같이 ORDER BY 를 추가해야 한다. ORDER BY 가 없으면 매 페이지를 읽을 때마다 데이터의 순서가 보장되지 않아 일부 데이터가 누락되거나 중복될 수 있다. 라고 했잖아. 이 말은 곧 " JpaCursorItemReader 는 ORDER BY를 추가하지 않아도 괜찮다"로 들리는데 맞아? GPT는 아니라고 하거든. cursor 기반도 마찬가지로 ORDER BY가 없으면 재실행마다 DB에 정렬 순서를 위임하는데, DB는 쿼리 플랜이 변경되는 등 여러 원인들에 의해 실행마다 달라질 수 있대. 뭐가 맞아?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 08:40 쯤에 public void changeTeam(Team team) { this.team = team; team.getMembers().add(this); } 이 부분에서, 내 팀을 변경해주고 변경할 팀에 해당 member를 넣어주는데 팀만 변경해 주면 되지 않나요? 따로 해당 team의 .getMember에 해당 멤버를 넣어주는 이유가 무엇인지 궁금합니다. 저장하기 전 까지는 해당 영속성에서는 이전 team에 할당이 되어 있어 수동으로 바꿔주는 것 인가요?
안녕하세요. 바인딩 에러와 관련해 어떤 의도로 if 절이 나뉜 것인지 정확히 이해를 못한것 같아서 질문드립니다. 메시지 작성에서 nullable 한 값이 존재하여 null-safe 하게 메시지 여부를 검사하고, 존재한다면 메시지를 반환해주는 것으로 이해를 하였습니다. 그리고 여러 필드에서 에러가 발생한 경우 람다식을 통해 에러 메시지를 "," 로 조합해주고 리턴을 하는 것으로 이해하였습니다. 이후 직접 테스트해보는 과정에서 localhost:8080/v1/books 으로 파라미터들을 모두 제외하고 요청을 보낸 경우의 기대가 "쿼리비어있을수 없습니다., 페이지..., 사이즈... 값들이 정확하지 않습니다." 이런 결과가 나오는 것으로 기대를 하였지만, 실제론 랜덤하게 누락된 값 하나만 결과로 나오는 것을 확인하였습니다. 혹시 e.getFieldErrors().stream() 가 default 메시지가 null 인 케이스만 방어하기 위해서 작성된 것일까요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 안녕하세요 영한님. 좋은 강의 만들어주셔서 감사합니다. 다름이 아니라, 제가 " 77강 빈 후처리기 - 적용 " 강의 내용을 따라가면서 겪은 exception 에 대해 공유드리고자 글 작성합니다. @Slf4j public class PackageLogTracePostProcessor implements BeanPostProcessor { private final String basePackage; private final Advisor advisor; public PackageLogTracePostProcessor(String basePackage, Advisor advisor) { this.basePackage = basePackage; this.advisor = advisor; } @Override public @Nullable Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { log.info("param beanName={} bean={}", beanName, bean.getClass()); // 프록시 대상 여부 체크 // 프록시 적용 대상이 아니면 원본 그대로 진행 String packageName = bean.getClass().getPackageName(); if (!packageName.startsWith(basePackage)) { return bean; } // 프록시 대상이면 프록시를 만들어서 반환 ProxyFactory proxyFactory = new ProxyFactory(bean); proxyFactory.addAdvisor(advisor); Object proxy = proxyFactory.getProxy(); log.info("create proxy: target={} proxy={}", bean.getClass(), proxy.getClass()); return proxy; } } 제가 강의 내용을 따라하면서 작성한 PackageLogTracePostProcessor 파일인데, 이 상태로 실행하면 Failed to instantiate [hello.proxy.app.v1.OrderControllerV1]: Illegal factory instance for factory method 'orderControllerV1'; instance: jdk.proxy2.$Proxy56 이라는 내용과 함께 exception 이 발생합니다. 이에 대한 원인은 아래와 같이 파악했습니다. AppV1Config 에 붙어있는 @Configuration 은 proxyBeanMethods 속성이 default 로 true 이며, 이로 인해 Spring Boot 는 AppV1Config 를 감싸는 CGLIB 프록시 객체를 생성합니다. (이하 AppV1Config::CGLIB 객체로 칭하겠습니다.) 이후 AppV1Config::CGLIB 객체는 PackageLogTracePostProcessor 로 들어오게 되고, ProxyFactory 를 통해 한번 더 프록시 객체로 감싸지게 됩니다. 이 때, AppV1Config::CGLIB 객체는 EnhancedConfiguration 라는 인터페이스를 구현하는 상태이며, 따라서 JDK Dynamic Proxy 객체로 생성이 됩니다. **앞선 강의에서 설명해주신 대로, JDK Dynamic Proxy 프록시 클래스는 원본 클래스와는 관련이 없습니다. (동일한 인터페이스만 구현하므로) 그래서 이후 AppV1Config 내부에 선언된 orderControllerV1 빈 객체를 생성하려 할 때, SimpleInstantiationStrategy.java 의 instantiate 메소드 내부에 있는 if (factoryBean != null && !factoryMethod.getDeclaringClass().isAssignableFrom(factoryBean.getClass())) 조건문에 걸려 BeanInstantiationException 이 발생하는 상황입니다. 혹시 제가 파악한 내용에 잘못된 부분이 있을지, 아니라면 이에 대한 적절한 대응 코드가 추가되어야 할 것 같은데, 한번 검토해주시면 감사하겠습니다!
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요 .어제 까지만 해도 잘 열리던 인텔리제이가 이런 문구가 뜨면서 열리지 않습니다. 이런 오류가 종종 발생하는 이유가 뭔지 해결방법에는 어떤게 있는지 예방방법은 어떤 것이 있는지 궁금합니다
안녕하세요. 강의 잘 듣고 있습니다. 다름이 아니라 프로젝트 의존성 관계를 그래프로 그려주셨는데요. 그려주신 그래프가 맞는걸까요..? bank-mornitoring은 아무런 모듈을 의존하지 않고, 반대로 bank-monitoring을 의존하는 모듈은 bank-api, bank-event인데 그려주신 그래프와 관계가 좀 다른거 아닌가 싶어 여쭤봅니다!
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 회원 객체 다이어그램에 클라이언트 -> 회원서비스 구현체 -> 회원저장소 이렇게 되어있는데 클라이언트는 구현체는 인터페이스에 의존해야하잖아요? 근데 왜 클래스 다이어그램에도 그렇고 객체 다이어그램에도그렇고 클라리언트 -> 회원서비스 구현체 -> 회원 저장소 이렇게 되어있는건가요???
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요. 좋은 강의 재미있게 잘 듣고 있습니다. 특별히 오류가 발생한 것은 아니고 강의를 수강하다가 한 가지 궁금한 점이 생겨 질문 남기게 되었습니다. 강의 앞 부분에서 OCP, DIP 같은 객체 지향 설계 원칙에 기반해서 DiscountPolicy 같은 것들은 인터페이스를 두고 실제 구현 객체를 구현하고, 그 구현 객체를 빈 객체로 등록하여 의존성을 주입 받으면서 코드를 작성해왔는데, 결국 @Qualifier 어노테이션을 통해 2개 이상의 구현 객체 중 한 가지를 지정하게 되면 인터페이스에 의존하는 것이 아닌 실제 구현 객체에 의존하게 되면서 OCP, DIP 같은 원칙에 위반되는 것이 아닌가? 이런 궁금증이 생겨서 질문합니다!
질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 스프링이 설정정보 없이 H2 데이터베이스 커넥션을 연결할 때 build.gradle에 dependencies 에 있는 H2를 읽고 커넥션을 연결하나요?
안녕하세요. 우선 좋은 강의 제작해주신 토비님께 항상 감사하고 있어요. 이제 배운지 1년된 왕초보입니당.. 혼자 배워보면서 개인 프로젝트를 만들고 있는데 JPA를 사용하고 있어요. 제가 궁금한 것이... N+1 관련한 문제입니다. 아 일단 프로젝트 주제는 복식부기 가계부에요. @Entity ... public class Journal extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "ledger_id", nullable = false, updatable = false) @OnDelete(action = OnDeleteAction.CASCADE) private Ledger ledger; ... @OneToMany(mappedBy = "journal", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) private List<EntryLine> entries = new ArrayList<>(2); ... public EntryLine getEntryLine(EntrySide side) { switch (side) { case CREDIT : this.entries.stream().filter(line -> line.isCredit()).findFirst() .orElseThrow(...); case DEBIT : this.entries.stream().filter(line -> line.isDebit()).findFirst() .orElseThrow(...); default : throw new ... } } ... // Service에서 저장되기 전에 호출 public void validateSavable() { ... validateJournalSave(); } private void validateJournalSave() { AccountType debit = getEntryLine(EntrySide.DEBIT).getAccountType(); AccountType credit = getEntryLine(EntrySide.CREDIT).getAccountType(); if(!this.transactionType.isValidPlacement(debit, credit)) { throw new ... } } } Journal Class에서 EntryLine List에 접근하고 있어요. 그리고 EntryLine Class는 이렇게 생겼어요. @Entity ... public class EntryLine extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "journal_id", nullable = false, updatable = false) private Journal journal; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "account_id", nullable = false) private Account account; ... // private package 접근제어자 사용 // Account는 Category를 참조중이에요. AccountType getAccountType() { return this.account.getCategory().getAccountType(); } } 거래가 저장되기 전에 Journal : validateJournalSave() 에서 this.transactionType에 따라 차변과 대변에 올바르게 위치하고 있는지 검사한 후 저장하고 있는데 이것을 생성과 수정할 때 두 곳에서 사용하고 있어요. Ledger에 5개 Category가 있고, Account는 그 Category를 참조하고 Category에서만 AccountType이 있어요. Journal이 각 EntryLine의 AccountType을 얻기 위해 Journal -> EntryLine -> Account -> Category -> getAccountType() 이렇게 흘러가네요. 이렇게 접근해도 설계상 괜찮은걸까요? Journal을 저장할때는 @Query 사용해서 Fetch Join으로 필요한 Account를 가져오고 있는 상황이에요. Journal이라는 엔티티가 비즈니스 로직 수행을 위해서 다른 엔티티의 필드까지 깊게 참조?? 가져오도록 설계하는게 옳은건지 모르겠어요.