안녕하세요. 백기선님. 좋은 강의 감사합니다. 강의를 따라가다 Authentication 오류 해결에 어려움을 겪고 있어 질문드립니다. test소스 authenticated()에서는 Authentication should not be null 에러가 발생하고 뷰단에서도 isAuthenticated() 체크되지 않습니다. 디버깅을 해보면 UsernamePasswordAuthenticationToken 생성 이후 Authentication 객체가 만들어진 것은 확인을 했는데, 어느 시점에서 객체를 못가져오고 null이 찍힙니다. 스프링시큐리티에 대한 지식이 없어 그런지 난감합니다. 도움주시면 감사하겠습니다. Spring-Security6 사용중입니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 김영한님 설명을 들어보면 @ManyToOne어노테이션이 다대일 관계에서 객체와 테이블을 매핑해준다고 하셧는데 , @ManyToOne이 사용되면 객체와 테이블을 매핑해줌과 동시에 테이블에서도 외래키를 생성해준다고 생각하면 맞을까요??
Junit5로 테스트를 생성해서 그런지 Test애노테이션에 expected 라는 옵션이 없어서 @Test() public void 상품주문_재고수량초과() throws Exception { //given Member member = createMember(); Item book = createBook(10000, 10, "시골 JPA"); int orderCount = 11; //when Assertions.assertThatThrownBy(() ->orderService.order(member.getId(), book.getId(), orderCount)) .isInstanceOf(NotEnoughStockException.class); } 이렇게 만들어서 돌렸는데 테스트가 통과했다면 그냥 넘어가도 되는 것일까요? @Test() public void 상품주문_재고수량초과() throws Exception { //given Member member = createMember(); Item book = createBook(10000, 10, "시골 JPA"); int orderCount = 11; //when Assertions.assertThatThrownBy(() ->orderService.order(member.getId(), book.getId(), orderCount)) .isInstanceOf(NotEnoughStockException.class); fail("재고 수량 부족 예외가 발생해야 한다."); } 이렇게 돌리면 재고 수량 부족 예외가 발생해야 한다. java.lang.AssertionError: 재고 수량 부족 예외가 발생해야 한다. 라는 예외가 발생했습니다.
public int getTotalPrice() { return orderPrice * count; } public int getTotalPrice() { return getOrderPrice() * getCount(); } 주문 아이템의 가격을 반환해야할 때 당연히 위처럼 코드를 작성해야겠다고 생각했는데, 강의를 보니 아래처럼 하시더라구요 결국 같은 값을 반환하는 것 같은데 어떤 차이가 있는지 알 수 있을까요 ?
섹션 4. 회원 도메인 개발 ] 회원 기능 테스트 강의를 수강하는 중 질문이 있습니다. @ExtendWith(SpringExtension.class) @SpringBootTest @Transactional // for rollback class MemberServiceTest { @Autowired MemberService memberService; @Autowired MemberRepository memberRepository; @Autowired EntityManager em; @Test @DisplayName("회원가입") @Rollback(false) public void signUp() throws Exception { // given Member member = new Member(); member.setName("kim"); // when Long saveId = memberService.join(member); // then Assertions.assertThat(member).isEqualTo(memberRepository.findOne(saveId)); } @Rollback(false) 어노테이션을 사용한 결과 강의와 동일하게 db의 member table에 name = "kim" 이 정상적으로 들어온 것을 확인하였습니다. 그런데 이후 @Rollback(false) 어노테이션을 주석 처리한 뒤 Test를 실행하면, 위에서 저장했던 name="kim" 의 row가 지워진 것을 확인할 수 있었습니다. 여기서 저의 궁금증은, 첫 번째의 결과로 인해 name = "kim" 인 row가 이미 생성이 되었으므로, 2번을 실행할 때 memberService.join 메서드에서 이미 기존의 name="kim"인 데이터가 있으므로 오류를 발생시켜야 한다고 생각했는데요, 결과는 정상적으로 테스트가 수행됩니다. 위의 이유를 잘 모르겠습니다. 감사합니다.
title이 글자수 10이 넘지 않으려면 Post클래스 title객체에다가 @Max(value=10,"10이 넘으면 안된다") 를 붙이면 해결되지 않을까요?? 만약 기존에 있던 글들이 글자수 10이 넘으면 오류가 날테니? 그에따른 try catch문으로 substring적용해서 글자 수 줄여주고요!
안녕하세요. 강의 영상보고 data jpa 를 사용해 프로젝트 진행중에 있습니다. 다름이 아니라 카운트 쿼리에 countQuery = "SELECT count(a) from Article a inner join fetch a.content where a.category =:categoryId and (a.title like %:keyword% or a.content.content like %:keyword%) join fetch 하면 에러가 발생하였고, 해다 에러 발생 이유는 구글링 후에 확인할 수 있었습니다. 이유: 그런데 여기서 문제는 fetch join은 객체 그래프를 조회하는 기능이기 때문에 연관된 부모가 꼭 있어야 합니다. 그런데 수를 뽑는 count(u)로 조회 결과가 변경되어버렸기 때문에, 오류가 발생한 것이지요. 그런데 하나 의문점이 생깁니다. 해당 쿼리 내용을 보면, join 한 엔티티의 요소를 where절에서 찾고 있습니다.( a.content.content like %:keyword%) 그런데 제가 알고 있는 개념으로는, 기본 Lazy loading 을 사용하게 되면, 연관되어 있는 엔티티를 프록시로 가져오는 것으로 알고 있습니다. 그렇게 되면 저 where절의 부분에서 content가 프록시로 들어갔기 때문에, 올바르게 동작하면 안된다고 생각합니다. fetch를 사용하지 않아도, inner join으로만 쿼리가 날라가도, 쿼리 자체는 전부 실행되는 것인가요? 그런데 가만히 생각해보면 그런 방식이라면, 지연로딩을 사용하는 방식이 사용자가 필요로 하지 않는 정보까지 join 하는 데이터베이스의 부하를 줄이기 위해 이렇게 하는 것으로 알고 있는데, fetch를 사용하지 않아도 데이터베이스에는 완전한 쿼리가 날라간다면, 이걸 굳이 스프링이 proxy로 끼워줄 필요가 있나? 하는 생각도 듭니다. 따라서 요약해보면, 카운트 쿼리에서 조건에 따라 count 가 달라지므로, join을 할 때 fetch 를 넣지 않아도, 올바르게 작동하는 것이 맞는지 맞다면 fetch를 사용하지 않아도 실제 데이터베이스에는 join 연산이 항상 일어나는 것이고, 대신 엔티티에 반환 해 줄 때, 프록시로 들어가는 것이고 fetch 를 사용하게 되면 나왔던 모든 결과가 엔티티로 들어가 는 것이 맞는지 입니다. jpa 책이랑 웹 전부 뒤져봤는데 이 부분이 약간 모호해서 질문드립니다!
formData.find('#id').remove(); formData.find('#title').remove(); formData.find('#content').remove(); formData.find('#writer').remove(); 에서 modify.jsp 파일에는 id 속성을 가지고 있는 태그가 없는데 #태그를 사용해서 remove()하는 이유가 무엇인가요?? #태그는 id속성과 일치하는 값을 가져오는 것으로 알고 있었는데 혼란스럽네요. https://github.com/bitcocom/spring2/blob/main/SpringMVC09/src/main/webapp/WEB-INF/views/board/modify.jsp
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. @Column에서 unique나 length제약조건을 거는것은 런타임에 영향을 주지 않는다 하시고 @Table에서 name을 사용해서 테이블 명을 바꾸는것은 런타임에 영향을 주신다고 하셧는데 둘의 차이를 이해하지 못하고 있습니다. @Table의 name을 변경하는것이 인서트 쿼리나 업데이트 쿼리에 영향을 준다고 하셧는데 이 말 자체를 이해하지 못하고 있는 것 같습니다..
K8S나 Docker Swarm 없이 2대 이상의 Host PC에 Multi Cluster를 구성할 수 있을까요? 혹시 2대의 PC에 각각 Docker를 설치하고, 여기에 분산되서 올라간 Container들을 하나의 Network으로 묶는것이 가능한가 해서요. 방법이 있으면 알고 싶습니다
Querydsl 강의 <섹션 7. 스프링 데이터 JPA가 제공하는 Querydsl 기능> 강의를 들으면서 QuerydslPredicateExecutor나 Querydsl Web 지원을 사용하게 되면 Controller나 Service에서 Querydsl에 의존하게 되니까 사용하는걸 권장하지 않는다고 말씀해주셨습니다. 스프링 데이터 JPA에서 Pageable을 사용하면 Controller나 Service에서 org.springframework.data .domain.Pageable 에 의존하게 됩니다. Spring Web과 Spring Data JPA 를 같이 사용하는 경우가 많기 때문에 Spring Web이 Spring Data JPA에 의존하게 되는건 크게 문제가 되지 않는건가요?
그림상에서 flush가 두번 찍혀있어서 매커니즘의 구동 순서가 조금 햇갈려서 그런데 1번의 flush와 4번의 flush의 의미가 조금 다른건가요? 아니, flush가 두번 동작하는건가요? 우선은 선생님께서 트랜잭션 커밋 요청 시 내부적으로 flush가 발생한다고 하셨습니다. flush의 동작과정이 1차 캐시의 최초 스냅샷과 수정된 Entity의 값을 비교하고 변경내용 있을 경우 저장소에 UPDATE쿼리 저장하고 쿼리를 실행하는것까지가 맞을까요? 그렇다면 쓰기지연의 경우에도 동일한 매커니즘처럼 보이는데 해당 그림에서는 flush가 빠져있어서 조금 햇갈리네요.. 쓰기지연의 경우는 persist 동작과정중에 따로 flush를 하지 않고 1차캐시에 저장됨과 동시에 쓰기지연 저장소에도 저장된다고 설명해주셨고, 이후에 트랜잭션 커밋 요청시 내부적으로 flush가 발생하면서 쿼리가 실질적으로 실행된다는 순서로 이해했습니다. 강의 내용상으로 요약해보면 [쓰기지연] persist호출 후 flush 호출 persist에서 INSERT 쿼리 저장 flush에서 저장된 쿼리 실행 [변경감지] flush가 두번 작동 첫번째 flush에서 변경감지후 UPDATE 쿼리 저장 두번째 flush에서 저장된 쿼리 실행 이렇게 차이가 나는걸로 이해를 했습니다. 두 매커니즘이 위와 같이 약간의 차이가 있는게 맞을까요? 그리고 추가적으로 엔티티 삭제 remove시에는 직전 내용인 변경감지와 동일한 매커니즘이라고 설명해주셨는데 아무리 생각해도 delete의 경우에는 변경감지의 매커니즘보다는 쓰기지연의 매커니즘과 같다고 생각이 들어서 질문드립니다! 질문드리기가 조금 까다로운내용이라 저의 궁금포인트가 이해가 되셨는지 모르겠네요... 영속성 관리 파트의 모든 강의를 들어야 명확하게 이해가 가능한건지 제가 너무 까다롭게 이해하려고 하는 건지 그래도 순서를 조금 철저히 명확하게 알아야 정확하게 JPA를 사용할수 있지 않을까 싶어 질문드리오니 너그러운 마음으로 답변 부탁드리겠습니다.
저장의 경우에 persist 이후 transaction commit시점에 쿼리를 날린다고 하신건 이해가 됬습니다. 혹시 그렇다면 find시에는 단순히 find해서 영속성을 두번 조회할때 로직 절차상으로는 member1을 영속화 하면서 1차캐시에 저장해둠과 동시에 SELECT쿼리가 나가고 member2를 조회할때 1차캐시에서 조회하는것에 대해서 이해가 되었습니다 혹시 이때에는 갱신에서의 절차와 같이 아래의 트랜잭션 commit과는 연관없이 find()시 바로 영속화와 Select쿼리를 동시에 날리는것인가요? 그리고 하나 더, JPA를 떠나서 스프링에서 데이터 처리를 하는 경우 readOnly=true 옵션인 SELECT에는 트랜잭션을 걸지 않아도 상관이 없는것 인지도 궁금합니다. 보통은 전체단위로 트랜잭션을 readonly default로 걸어주고 삽입 혹은 삭제 등의 갱신에서 추가적으로 readOnly=false옵션을 걸어주는방식으로 개발을 진행해왔습니다.