학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. @PatchMapping("/api/v2/members/{id}") public UpdateMemberResponse updateMember(@PathVariable("id") Long id, @RequestBody @Valid UpdateMemberRequest updateMemberRequest) { 수정 api는 위와 같은 주소를 이용합니다. 근데 사실 UpdateMemberRequest에 id라는 필드를 넣고 주소를 /api/v2/members 로 둬도 상관 없지 않나요? id를 PathVariable로 뺀 이유가 궁금합니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 엔티티를 api로 넘겨주면 엔티티가 수정됐을때 api가 오염될 수 있는 문제가 있어서 응답에 DTO를 보내준다고 이해했습니다. 근데 이 문제는 탬플릿 엔진을 사용해 화면을 출력할때도 문제가 되지 않나요? 1편에서 타임리프에 값을 넣을때는 DTO를 이용하지 않은 이유가 궁금합니다. 혹시 컴파일 단계에서 오류가 나기 때문인가요?
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? ( 예 /아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? ( 예 /아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? ( 예 /아니오) [질문 내용] 어느 순간 갑자기 hello-spring 프로젝트를 켰을때 실행버튼이 안눌리고 HelloSpringApplication에서도 메서드에 재생 버튼이 안뜹니다. 왜그러죠? edit configuartion 해야하나요
>java -jar jpashop-0.0.1-SNAPSHOT.jar 하는 단계에서 계속 오류가 납니다... Web server failed to start. Port 8080 was already in use. 라고요... 8080포트가 사용중이라는데 cmd 관리자권한으로 실행해서 8080의 pid 는 찾아도 taskkill 이 안돼요 이렇게 뜨고 인터넷창에서 8080 접속하면 static 폴더 안에 있는 파일인 이 페이지가 떠요.... 왜이럴까요? 계속 해도 안되네요....
https://www.inflearn.com/community/questions/48156/aop-timetraceaop-%EB%A5%BC-component-%EB%A1%9C-%EC%84%A0%EC%96%B8-vs-springconfig%EC%97%90-bean%EC%9C%BC%EB%A1%9C-%EB%93%B1%EB%A1%9D @Configuration 파일 내에서 @Bean 어노테이션을 사용하여 TimeTraceAop.java 파일을 빈으로 등록하는 경우, 참조 문제가 발생하는 부분에 대해 위 다른 분이 작성해주신 글을 통해 이해가 잘 갔는데요, 그럼 @Component 어노테이션을 활용하여 등록하는 경우에는 동일한 @Around 구문을 통해 명시된 @Around("execution(* hello.hellospring..*(..))")를 사용하는 경우 문제가 발생하지 않는 것인지 궁금합니다.
https://drive.google.com/file/d/1M-NYH5etfTZPV5kMZzuiOWaBjA7bR3XR/view?usp=sharing 위는 제 프로젝트 파일입니다 강의 파일에 나와있는부분을 복붙해도 오류나고 testImplementation("junit:junit:4.13.2") 이렇게 해도 오류납니다. Assert 부터 안되는데 뭐가 잘못된걸까요?
배운거를 적용하면서 쿼리 개선을 하고 있었는데, 혼자 해결해보려고 했으나 컬렉션 조회가 같이 섞이면서 이해가 잘 안 되는 것 같아 질문을 남기게 되었습니다. 게시글 목록을 불러올때 태그이름 리스트를 같이 필요하기 때문에 관련 memePostTags와 Tag까지 같이 조회를 해야하는 상황입니다. 테이블 관계가 MemePost 1 : N MemePostTag 1 : 1 Tag 이렇게 되어있을때 getMemePost5 메서드와 getMemePost6메서드 둘 중에 어느 것이 더 나은 방법인지, 아니면 더 나은 다른 방법이 있는지 궁금합니다. getMemePost5의 경우는 MemePostTagRepository에서 Tag까지 fetch join으로 불러오고, Map 객체에 postId를 key로 저장해서 태그 이름을 조회합니다. getMemePost6의 경우는 페이징으로 조회한 후 postIds를 in절로 postTag와 tag를 fetch join합니다. 컬렉션 조회의 경우 페이징을 안할 경우 fetch join으로, 페이징을 할 경우 batch size로 하라는 것까지는 이해가 되었는데, 이 경우에는 postTags를 batch size로 가져오고, 그에 다한 tag도 batchsize로 가져와 추가로 두번의 쿼리가 더 나가게 되어서 다른 방법을 고안해내다가 점점 미궁으로 빠지는 것 같아서 질문을 남기게 되었습니다 😂 public Slice<MemePostSummaryResponse> getMemePosts5(int page, int size, MemePostSort postSort, Long userId) { Pageable pageable = PageRequest.of(page, size, postSort.toSort()); Slice<MemePost> memePostSlice = memePostRepository.findSliceAll(pageable); List<Long> postIds = getPostIds(memePostSlice.getContent()); // MemePostTag와 Tag를 한번에 fetch join 하나의 쿼리로 하되, MemePostTagRepository에서 entitygraph를 통해 fetch join Map<Long, List<String>> postTagNames = memePostTagRepository.findTagsByMemePostIdIn(postIds) .stream() .collect(groupingBy(tag -> tag.getMemePost().getId(), mapping(tag -> tag.getTag().getName(), toList()))); //좋아요도 하나의 쿼리로 Set<Long> likedPostIds = new HashSet<>(memePostRepository.findLikedPostIds(postIds, user)); List<MemePostSummaryResponse> responses = memePostSlice.getContent().stream() .map(mp -> new MemePostSummaryResponse( mp, likedPostIds.contains(mp.getId()), postTagNames.getOrDefault(mp.getId(), Collections.emptyList()) )) .toList(); return new SliceImpl<>(responses, pageable, memePostSlice.hasNext()); } public Slice<MemePostSummaryResponse> getMemePosts6(int page, int size, MemePostSort postSort, Long userId) { Pageable pageable = PageRequest.of(page, size, postSort.toSort()); Slice<MemePost> memePostSlice = memePostRepository.findSliceAll(pageable); List<Long> postIds = getPostIds(memePostSlice.getContent()); // MemePostTag와 Tag를 한번에 fetch join memePostRepository.findAllWithTagsInPostIds(postIds); //좋아요도 하나의 쿼리로 Set<Long> likedPostIds = new HashSet<>(memePostRepository.findLikedPostIds(postIds, user)); List<MemePostSummaryResponse> responses = memePostSlice.getContent().stream() .map(mp -> new MemePostSummaryResponse( mp, likedPostIds.contains(mp.getId()), mp.getTagNames() )) .toList(); return new SliceImpl<>(responses, pageable, memePostSlice.hasNext()); } public interface MemePostRepository extends JpaRepository<MemePost, Long>, MemePostRepositoryCustom { @Query("SELECT mp FROM MemePost mp where mp.deletedAt IS NULL") Slice<MemePost> findSliceAll(Pageable pageable); @Query("SELECT mp.id FROM MemePost mp " + "JOIN MemePostLike mpl ON mpl.memePost = mp " + "WHERE mp.id IN :postIds AND mpl.user = :user") List<Long> findLikedPostIds(@Param("postIds") List<Long> postIds, @Param("user") User user); @Query("SELECT mp FROM MemePost mp " + "LEFT JOIN FETCH mp.memePostTags mpt " + "LEFT JOIN FETCH mpt.tag " + "WHERE mp.id In :postIds") List<MemePost> findAllWithTagsInPostIds(@Param("postIds") List<Long> postIds); } public interface MemePostTagRepository extends JpaRepository<MemePostTag, Long> { @EntityGraph(attributePaths = {"tag"}) List<MemePostTag> findAllByMemePostId(Long postId); @EntityGraph(attributePaths = {"tag"}) List<MemePostTag> findTagsByMemePostIdIn(List<Long> memePostIds); } public class MemePost { public List<String> getTagNames() { return memePostTags.stream() .map(mpt -> mpt.getTag().getName()) .toList(); } }
[질문 내용] 안녕하세요, 강의 중에 궁금한점이 있어 글 남깁니다. 스프링 부트 스타터에 톰캣이 인베디드 되어서 저절로 가져오기 때문에 서버에 따로 톰캣을 설치할 필요가 없다고 하셨는데, 그렇다면 각 프로젝트를 서버에 띄우게 되면 모두 톰캣이 멀티 인스턴스로 띄우고 각 프로젝트는 모두 다른 포트를 사용해야하는걸까요? 만약 그렇다면 각 프로젝트에 톰캣 포트 세팅을 따로 해주어야하는데 해당 부분은 서버에서 하는게 아닌 프로젝트를 배포할때 세팅 파일에 따라 세팅이 되는 걸까요?
안녕하세요 지식공유자님. User 클래스의 credentials 필드에 lazy loading 관련하여 설명을 해주셨는데요, 제가 알기로는 mappedBy 가 있는 쪽에서는 LAZY 로딩이 동작하지 않는 것으로 알고 있습니다. 즉, 연관관계의 주인인 UserCredentails 쪽에만 적용하는 것이 맞다고 생각이 드는데 제 생각이 맞을까요?
안녕하세요 지식 공유자님. MySqlConfig 클래스에 대해 질문이 있습니다. yml 에 이미 mysql 정보들을 설정했는데 MySqlConfig 클래스에서도 @Value 를 통해 설정정보를 또 작성하는 것은 무엇을 위함인것일까요? 제가 알기로는 Spring Boot의 자동 설정이 application.yml의 설정들을 자동으로 읽어와서 DataSource bean으로 구성하는 것으로 알고있는데 다시 작성하는 이유가 궁금합니다. 감사합니다.
자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
안녕하세요 선생님. 실습 과정중 mysql과 연결이 잘 안 되는 것 같아 질문드립니다 처음에 있었던 에러였는데요 화면 접속 자체는 잘 되는데 이름과 나이를 저장하면 2024-11-28 16:57:49.886 ERROR 13764 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.group .libraryapp.dto.user.request.UserCreateRequest]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.group.libraryapp.dto.user.request.UserCreateRequest (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 2]] with root cause com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.group.libraryapp.dto.user.request.UserCreateRequest (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 2] 이런 오류가 떴습니다. 검색해보니 UserCreateRequest에 기본 생성자를 만들라고 해서 만든 후 실행하니 이 오류는 안뜨긴합니다. 인자 있는 생성자가 있었는데 왜 기본 생성자를 만들어야하는건가요? 지금 제 코드가 꼬여서 그런걸까요? 또한 에러 해결 방법으로 애노테이션 누락 : Jackson 라이브러리에서 객체를 직렬화/역직렬화할 때 필요한 애노테이션이 누락되었을 수 있습니다. 예를 들어, 생성자에 @JsonCreator 와 각 필드에 @JsonProperty 를 추가해 보세요. 이런 방법을 추천하는데 이건 무엇인가요?? 위 에러 고친 이후에는 SQL 문법 오류가 발생하는데요 선생님과 똑같이 문법을 사용했는데 왜 오류가 생기는지 모르겠습니다.. sql에 테이블 자체는 잘 생성되어있는 상태입니다
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? ( 예 /아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? ( 예 /아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 회원 리포지토리 테스트 케이스 작성중 4:43 test 결과 저만 -1 나오는게 비정상인가요? package hello.hello_spring.repository; import hello.hello_spring.domain.Member; import org.junit.jupiter.api.Test; class MemoryMemberRepositoryTest { MemberRepository repository = new MemoryMemberRepository(); @Test public void save() { Member member = new Member(); member.setName("spring"); repository.save(member); //repository.findById(member.getId()); Member result = repository.findById(member.getId()).get(); System.out.println("result = " + (result == member)); } }
의문점이있습니다. public interface UsernameOnly { String getUsername(); } 이런식으로 사용자 이름만 가져올수있게 하는건 알겠는데 그냥 레파지토리에 @Query("select m.userName from Member m ") 그냥 이런식으로 하면되는거아닌가요?굳이 projection안쓰고?햇갈립니다