현재 실전 데이터 JPA수강 중인데요.. 독학 중이라 토이프로젝트로 연습하는데 오늘까지 배운 JpaRepository 상속과 관련하여 회원가입 기능 구현하려 하려는데 어디 물어볼곳이 없고 뒤죽박죽이라 정리가 필요해서 장문의 질문을 남깁니다.. 일단 제가 머릿속에 정리가 안되는 것은 영한선생님께서 최대한 컨트롤러에 엔터티를 노출하지 말고 비지니스 로직을 서비스에서 최대한 구현하라고 해서 따라하는 중인데 Member를 기준으로 파라미터를 받을 MemberForm을 생성했습니다. 여기서 질문이.. MemberForm을 생성했으면 MemberDto는 따로 생성 안해도 될까요? 컨트롤러를 그림과 같이 작성하였고 서비스는 아래와같이 하였는데... 뭔가 서비스에서 엔터티를 직접 만지니까 찝찝한데 실무에서도 이렇게 하는지 궁금합니다..
는 어떻게 하는 것이 좋은 건가요? PK이자 글 번호인 boardSeq를 가지고 와서 수정과 삭제를 진행하고 있었는데, PK는 최대한 외부로 노출하지 않는 것이 좋다고 하여서 문득 생각이 들었습니다. PK Seq를 따로 두고 UniqueKey로 똑같이 AutoIncrement해서 생성하게 된다면 결국 무슨 차이인가 싶어서 아닌 거 같기도 하고... 어떤 식으로 처리 해야 되는지 궁금하여 질문 남기게 되었습니다.
회원 A테이블과 팀C 테이블의 다대다 양방향 관계를 풀기 위해 중간 테이블을 도입하여 A, B(중간테이블), C 와 같이 일대다/다대일 관계로 풀어낼 때 A와 C 양 쪽 모두 addTemMember와 같은 메소드를 만들어주고, 회원이 팀에 들어갈 때 A.addTeamMember와 C.addTeamMember()둘 다 호출해줘야 하는 게 맞나요? 다대다 양방향 관계를 풀 때 중간 테이블을 설정하는데 이것은 따로 외부에 노출할 필요 없이, 내부적으로 회원 A가 어떤 팀에 속해있는지, 팀C에 어떤 회원이 속해있는지 확인할 때만 사용하는 것이 맞나요?
강의 내용을 보면 상품 목록 화면에서 item.id 값을 뿌려주고 있습니다. 이건 DB 에 저장된 item 테이블의 PK 값 일텐데, 문득 이런 생각이 들었습니다. DB 데이터 관리를 위한 PK 를 클라이언트 단에 노출시켜도 되나요? (가급적 엔티티 객체를 클라이언트 단에 직접 노출시키지 말라고 하셔서, 이것도 비슷한 맥락으로 숨겨야되지 않을까 해서요)
plugins { id 'java' id 'org.springframework.boot' version '3.2.2' id 'io.spring.dependency-management' version '1.1.4' } group = 'hello' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' // implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.h2database:h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() } 자바 17 로 잘되어있고 한데 자꾸 무슨 21이 보이고 웹에서는 정상 작동 하는데 테스트에서만 문제가 발생합니다. 해결 부탁드립니다. ㅠㅠ WARNING: A Java agent has been loaded dynamically (C:\Users\ㅋㅋ\.gradle\caches\modules-2\files-2.1\net.bytebuddy\byte-buddy-agent\1.14.11\f9cb566608fbac6bc7bf54901a7aa11543a989ee\byte-buddy-agent-1.14.11.jar) WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information WARNING: Dynamic loading of agents will be disallowed by default in a future release 2024-01-31T22:27:28.360+09:00 WARN 3716 --- [ main] o.s.test.context.TestContextManager : Caught exception while invoking 'beforeTestMethod' callback on TestExecutionListener [org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener] for test method [public void hello.hellospring.sevice.MemberServiceIntegrationTest.회원가입() throws java.lang.Exception] and test instance [hello.hellospring.sevice.MemberServiceIntegrationTest@7901a5ab] java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null) at org.mockito.internal.configuration.plugins.PluginLoader$1.invoke(PluginLoader.java:84) ~[mockito-core-5.7.0.jar:na] at jdk.proxy2/jdk.proxy2.$Proxy112.getHandler(Unknown Source) ~[na:na] at org.mockito.internal.util.MockUtil.getMockHandlerOrNull(MockUtil.java:158) ~[mockito-core-5.7.0.jar:na] at org.mockito.internal.util.MockUtil.isMock(MockUtil.java:147) ~[mockito-core-5.7.0.jar:na] at org.mockito.internal.util.DefaultMockingDetails.isMock(DefaultMockingDetails.java:32) ~[mockito-core-5.7.0.jar:na] at org.springframework.boot.test.mock.mockito.MockReset.get(MockReset.java:106) ~[spring-boot-test-3.2.2.jar:3.2.2] at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:85) ~[spring-boot-test-3.2.2.jar:3.2.2] at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:73) ~[spring-boot-test-3.2.2.jar:3.2.2] at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.before:na] at org.mockito.internal.configuration.plugins.DefaultMockitoPlugins.create(DefaultMockitoPlugins.java:103) ~[mockito-core-5.7.0.jar:na] ... 67 common frames omitted Caused by: org.mockito.exceptions.base.MockitoInitializationException: Could not initialize inline Byte Buddy mock maker. It appears as if your JDK does not supply a working agent attachment mechanism. Java : 21 JVM vendor name : Oracle Corporation JVM vendor version : 21.0.1+12-29 JVM name : OpenJDK 64-Bit Server VM JVM version : 21.0.1+12-29 JVM info : mixed mode, sharing OS name : Windows 10 OS version : 10.0 at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.<init>(InlineDelegateByteBuddyMockMaker.java:260) ~[mockito-core-5.7.0.jar:na] at org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker.<init>(InlineByteBuddyMockMaker.java:23) ~[mockito-core-5.7.0.jar:na] at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62) ~[na:na] ... 70 common frames omitted Caused by: java.lang.IllegalArgumentException: null at java.instrument/sun.instrument.InstrumentationImpl.appendToClassLoaderSearch0(Native Method) ~[na:na] at java.instrument/sun.instrument.InstrumentationImpl.appendToBootstrapClassLoaderSearch(InstrumentationImpl.java:280) ~[na:na] at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.<clinit>(InlineDelegateByteBuddyMockMaker.java:177) ~[mockito-core-5.7.0.jar:na] ... 72 common frames omitted 2024-01-31T22:27:28.368+09:00 WARN 3716 --- [ main] o.s.test.context.TestContextManager : Caught exception while invoking 'afterTestMethod' callback on TestExecutionListen
keycloak 버전이 제일 낮은 게 20 버전이라서 저는 가장 최근 버전인 23 버전으로 사용했습니다. 23 버전 기준으로, 제가 파악한, 강의와 다른 부분입니다. 20 버전부터는 최초 로그인 할 때 동의 항목이 안 나올텐데요. 관리자 콘솔에서 Clients -> Cliend details에서 Login settings에서 Consent required를 켜면 됩니다. 엑세스 토큰 발급 이후에 userinfo 엔드포인트로 user 데이터를 요청하면 body에 아무 것도 안 나올 겁니다. 응답 헤더 살펴보면 insufficient_scope이며 Missing openid scope이라고 나오는데요. 이렇게만 써있으면 userinfo 요청할 때 param에 scope=openid 넣으면 될 것 같지만 안 됩니다. 토큰에 해당 정보가 없는 거라서, 토큰 발급 전에(code 얻어야할 때) scop에 openid를 추가하면 됩니다. http://localhost:8080/realms/oauth2/protocol/openid-connect/auth?response_type=code&client_id=oauth2-client-app&scope=profile email openid&redirect_uri=http://localhost:8081 공식문서 에 나와 있습니다. In case an access token is missing openid scope.
List<ContentsDtoRes> contents = queryFactory .selectFrom(ParentEntity) .leftJoin(ParentEntity.childList, childEntity) .leftJoin(childEntity.childChildEntity, childchildEntity) .where( systemDelYnEq(condition.getDelYn()), autoDelYnEq(condition.getDelYn()) ) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) .transform( groupBy(systemEntity.sysId).list( new QContentsDtoRes( parentEntity.a, parentEntity.b, parentEntity.c, parentEntity.d, parentEntity.e, list( new QChildDto( childEntity.a, childEntity.b ) ), list( new QchildChildDto( childChild.a, childChild.b, childChild.c, childChild.d ) ) ) ) ); 안녕하세요 강사님. ㅎ Querydsl 의 일대다 관계에 대해서 질문이있어 올리게되었습니다. 예를들어 위와 같이 부모엔티티와 자식엔티티의 일대 다 관계가 될 경우 ParentEntity 는 존재하고 childEntity 가 없을 경우 querydsl 에서는 NPE 가 아닌 빈객체를 반환하게 되는데 아래와 같이 @QueryProject 생성자 하위에서 이렇게 빈객체를 체크하고 비워주는 작업을 할 수 밖에 없는건가요.? this.childList.addAll(childList.stream() .filter(child -> child.getId() != null).collect(Collectors.toList())); this.childChildList.addAll(childChildList.stream() .filter(childchild -> childchild.getId() != null).collect(Collectors.toList())); } 혹시 다른 방법이 있다면 어떤 방법이 있을지 궁금합니다. 항상 좋은강의 감사합니다.! 좋은하루되세요
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 여기에 질문 내용을 남겨주세요. cascadeType.all! 일단 저장할때 자식 객체를 다 담은 후 이후 부모 를 repository.save (부모) 하면 자식도 함께 저장되는 것을 강의 내용을 통해서 확인했습니다. 그러면 혹시 이 과정에 대해서는 어떻게 생각하시나요 Program program = programRepository.findById(reviewSaveDto.getProgramId()) .orElseThrow(() -> new NotFoundException(ErrorCode.PROGRAM_NOT_FOUND)); Review review = Review.builder() .content(reviewSaveDto.getContents()) .user(user) .program(program) .rating(reviewSaveDto.getRating()) .genre(usersFirstGenre.getName()) .build(); program.addReview(review); 보시면 program 을 리포지토리에서 찾아와서 Review 를 직접 생성한 후 addReview(review) 를 통해서 저장합니다. @OneToMany(mappedBy = "program", cascade = CascadeType.ALL, orphanRemoval = true) private List<Review> reviewList = new ArrayList<>(); public void addReview(Review review) { this.reviewList.add(review); 당연히 cascade가 발라져있고요!. 이러면 코드는 정상동작합니다. 저는 뭔가 ReviewRepository에서 program 세팅하고 이러는 것 보다 위 방법이 더 뭐랄까 직관적이다?(프로그램.addReview가 직관적이라는 느낌) 이라서 이 것을 애용했는데 성능 상의 문제점이라던가 이런게 있을지 궁금합니다. addReview 를 한다고 바로 저장되지 않고 트랜잭션이 끝날때 변경 감지를 통해서 실행되는것 같은데(뇌피셜입니다) . 이렇게 해도 괜찮을지 궁금해요!!! 영한님!!!
자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
아마존 리눅스 2023으로 인스턴스를 사용했을 때 지면님과 강사님께서 알려준 el9 버전 레포지토리를 사용하는 명령어 sudo dnf install <https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm> sudo dnf install mysql-community-server 이렇게 하여도 저는 계속 sudo dnf install mysql-community-server 해당 명령어를 통해 설치하려고 하면 The GPG keys listed for the "MySQL 8.0 Community Server" repository are already installed but they are not correct for this package. 이런 오류가 발생하였습니다. 계속 키가 옳지 않다는 오류가 생겼고 챗지피티랑 구글링을 통해 이것저것 해보다가 sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 sudo yum update 위의 두 명령어를 실행하고 sudo dnf install mysql-community-server 해당 명령어로 재설치 해주니 제대로 설치가 되었습니다! 제 추측으로는 KEY를 다시 받아오고 yum update 하는 과정이 필요했던 것 같습니다! 저와 같은 오류를 가지는 분들에게 도움이 되었으면 좋겠네요...!!!
fetchResults(), fetchCount()가 deprecated됐는데 강의에서 fetchResults()가 사용되는 QueryResults<Member> queryResults = queryFactory .selectFrom(member) .orderBy(member.username.desc()) .offset(1) .limit(2) .fetchResults(); 이런 코드들은 어떻게 바꿔야 하나요? 강의자료에 나와있지 않은 것 같습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 강의에서는 주로 H2 데이터베이스를 활용해 강의를 진행해주시는데, 실무에서는 데이터베이스를 다룰 때 보통 어떤 툴을 사용하는 지 궁금합니다.
========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 네 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 네 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 네 [질문 내용] 영한님 강의에서는 위와 같이 두 행의 데이터가 잘 조회되는데, 2024 버전으로 설치한게 잘못인건지 두번 쿼리를 날렸는데 이전 행에 덮어 씌워져 버리는 현상이 있습니다... 이유가 뭔지 모르겠네요 혹시 아시는분 답변 부탁드려요
안드로이드 스튜디오 arctic fox를 다운받고 첫 프로젝트를 생성했는데 코드가 쭉 빨간줄이 쳐지면서 밑에 사진과 같이 32개정도의 오류가 생기네요 뭐가 문제일까요? 아 그리고 이건 오류랑 다른 질문인데 저 arctic fox 버전에서 새로운 프로젝트를 생성했을때 생성되는 기본코드랑 지금 최신 버전인 Hedgehog 버전에서 만들어지는 기본코드랑 다르던데 원래 그런걸까요? 강의를 들을때 기본코드가 달라서 헷갈리더라구요
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 멤버 객체, 팀 객체 둘 중 하나로 MEMBER 테이블의 외래키를 관리해야 한다는 부분이 깔끔하게 이해가 가지 않아서 질문 드립니다. 제가 이해한 내용이 맞는지 확인 부탁드리겠습니다. 결국에 멤버 객체와 팀 객체가 서로를 호출하거나 업데이트하는데 사용하는 테이블은 멤버 테이블과 팀 테이블의 조인으로 생긴 하나의 테이블인데, 하나의 테이블이 2개의 객체와 매핑된다면 문제가 발생한다.(팀 객체가 갱신한 내용이 멤버 객체에 반영되지 않는 등의 문제) 그렇기 때문에 연관관계의 주인을 설정하여 한 객체만 실제로 테이블과 매핑하고 나머지 하나는 매핑된 객체로 부터 미러링된 내용을 사용(읽기 전용)한다. 이렇게 이해하는게 맞는 걸까요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] override오류로 test 작동이 안됩니다ㅠ
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. @JsonIgnore을 어느 클래스에 어디어디 붙여야 할까요? " http://localhost:8080/api/v1/simple-orders " api 테스트를 해보니 아래와 같은 에러가 나서 질문드립니다 2024-01-25T22:37:28.102+09:00 DEBUG 32028 --- [nio-8080-exec-1] org.hibernate.SQL : select o1_0.order_id, o1_0.delivery_id, o1_0.member_id, o1_0.order_date, o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id fetch first ? rows only 2024-01-25T22:37:28.226+09:00 ERROR 32028 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed: java.lang.NoClassDefFoundError: javax/persistence/Transient] with root cause java.lang.ClassNotFoundException: javax.persistence.Transient at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na] at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[na:na] 2024-01-25T22:37:28.277+09:00 ERROR 32028 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost] : Exception Processing ErrorPage[errorCode=0, location=/error] jakarta.servlet.ServletException: Handler dispatch failed: java.lang.NoClassDefFoundError: javax/persistence/Transient
========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예 [질문 내용] 강사님께서 양방향은 최대한 지양하고 단방향만을 이용해서 설계하고 나중에 굳이 필요하다면 양방향을 추가해라 라고 말씀하셨고 일대다 단방향, 일대일도 지양하고, 다대다는 풀어쓰라고 하셨는데요. 다대다를 풀게 되면 1:N 양방향, N:1 양방향이 되고 결국 연관관계를 설정할 때는 N:1 단방향, 다대다(1:N 양방향, N:1 양방향) 만을 가지고 설계하는 것이 가장 좋은 방법인가요 ?