자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
강의 04:40초 부분인데요 public void saveUser(UserCreateRequest request) { User u = userRepository.save(new User(request.getName(), request.getAge())); throw new IllegalArgumentException(); } 이부분에서 예외를 주고 서버를 띄어서 확인을 했는데 저렇게 "서버 내부 오류입니다" 라고 뜨는 것은 예외를 던져주면 자동으로 저렇게 뜨게 설정되어있는 건가요? 아니면 이렇게 예외를 던지면 ui에서 이렇게 띄어줘 라고 설정을 해주신건가요?
이번 강의 코드와 100% 유사한 백준 문제가 있어서 풀었는데 98%에서 오답처리 되었습니다. 강사님의 강의를 이해하고 풀다보니 강의와 코드가 똑같은데 왜 오답이 나오는건가요?? https://www.acmicpc.net/problem/11053 제 코드는 이렇습니다. import java.util.*; class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] arr= new int[n]; for(int i=0; i<n; i++) arr[i] = sc.nextInt(); int[] dp= new int[n]; int answer=0; dp[0]=1; //solve for(int i=1; i<n; i++){ int tmp=0; for(int j=i-1; j>=0; j--){ if(arr[i] > arr[j]) tmp=Math.max(tmp, dp[j]); } dp[i]=tmp+1; answer=Math.max(answer,dp[i]); } System.out.println(answer); } }
[질문 내용] 여기에 질문 내용을 남겨주세요. 둘다 save 메서드가 있는데 itemRepository 에서 save와 MemberRepository save에서 저장을 하게되면 아직 db에 insert를 한게 아니기 때문에 item이나 member은 id값은 먼저 null인 상태에서 메서드에 들어가고 em.persist을 하게되면 member은 바로 db에 들어가 id를 부여 받고 item도 당연히 null이니까 db에 들어가 id를 부여 받는 것이죠? member은 수정할 일이 없는데 item은 수정할 일이 있기 때문에 item의 id값이 있으면 em.merge로 수정할 수 있는 로직을 넣은 거구요 제가 이해한 것이 맞을까요?
안녕하세요. 아래 코드를 실행 시키면, hello 만 출력이 되어야 될것 같은데..world 도 같이 출력이 됩니다. get() 을 하면 동일 scope 에 있는 모든 CompletableFuture 가 실행이 되는것이 맞는 건지 문의 드려요. 감사합니다. CompletableFuture<String> hello = CompletableFuture.supplyAsync( () -> { System.out.println("Hello Thread : " + Thread.currentThread().getName()); return "Hello"; } ); CompletableFuture<String> world = CompletableFuture.supplyAsync( () -> { System.out.println("World Thread : " + Thread.currentThread().getName()); return "World"; } ); hello.get();
안녕하세요. 좋은 강의 정말 재미있게 잘 수강하고 있습니다. '상속과 메서드 오버라이딩' 강의 내용 관련하여 궁금한 점이 생겨 질문 드립니다. A와 B는 강의에서 설명해주신 내용입니다. [A.상속시 메모리 구조] 상속한 클래스의 메서드를 호출하는 경우에 1)본인 타입에서 해당 메서드를 먼저 찾고 2-1) 없으면 부모 타입에서 찾는다 2-2) 있으면 종료 [B. @Overriding] 자식 클래스의 메서드에 @Overriding 애노테이션을 붙여 오버라이딩 수행 시, 부모 클래스에 해당 메서드가 존재하지 않으면 컴파일 오류가 발생 그런데 여기에서 B 처럼 동작하려면 A의 2-2 경우에 자식 타입만 조사하고 종료하는 것이 아니라, 컴파일 타임에 부모 클래스의 메서드도 조사해야하지 않나요? @Overriding 애노테이션을 사용했을 때 실제로 어떤식으로 동작하는지 궁금합니다. 감사합니다.
자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
하나는 "NullPointerException: Cannot invoke "String.length()" because "<parameter1>" is null" 이런 에러인거 같은데....대체 어디서 잘못된걸까요. 에러가 여러개 인건가요? FAILURE: Build completed with 2 failures. 1: Task failed with an exception. ----------- * What went wrong: Execution failed for task ':app:checkDebugAarMetadata'. > A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction > 5 issues were found when checking AAR metadata: * Try: > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. * Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:checkDebugAarMetadata'. Caused by: org.gradle.workers.internal.DefaultWorkerExecutor$WorkExecutionException: A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction Caused by: java.lang.RuntimeException: 5 issues were found when checking AAR metadata: 1. Dependency 'androidx.appcompat:appcompat-resources:1.7.0' requires libraries and applications that depend on it to compile against version 34 or later of the Android APIs. :app is currently compiled against android-33. Also, the maximum recommended compile SDK version for Android Gradle plugin 8.0.0 is 33. Recommended action: Update this project's version of the Android Gradle plugin to one that supports 34, then update this project to use compileSdk of at least 34. Note that updating a library or application's compileSdk (which allows newer APIs to be used) can be done separately from updating targetSdk (which opts the app in to new runtime behavior) and minSdk (which determines which devices the app can be installed on). 2. Dependency 'androidx.appcompat:appcompat:1.7.0' requires libraries and applications that depend on it to compile against version 34 or later of the Android APIs. :app is currently compiled against android-33. Also, the maximum recommended compile SDK version for Android Gradle plugin 8.0.0 is 33. Recommended action: Update this project's version of the Android Gradle plugin to one that supports 34, then update this project to use compileSdk of at least 34. Note that updating a library or application's compileSdk (which allows newer APIs to be used) can be done separately from updating targetSdk (which opts the app in to new runtime behavior) and minSdk (which determines which devices the app can be installed on). 3. Dependency 'androidx.core:core-ktx:1.13.0' requires libraries and applications that depend on it to compile against version 34 or later of the Android APIs. :app is currently compiled against android-33. Also, the maximum recommended compile SDK version for Android Gradle plugin 8.0.0 is 33. Recommended action: Update this project's version of the Android Gradle plugin to one that supports 34, then update this project to use compileSdk of at least 34. Note that updating a library or application's compileSdk (which allows newer APIs to be used) can be done separately from updating targetSdk (which opts the app in to new runtime behavior) and minSdk (which determines which devices the app can be installed on). 4. Dependency 'androidx.core:core:1.13.0' requires libraries and applications that depend on it to compile against version 34 or later of the Android APIs. :app is currently compiled against android-33. Also, the maximum recommended compile SDK version for Android Gradle plugin 8.0.0 is 33. Recommended action: Update this project's version of the Android Gradle plugin to one that supports 34, then update this project to use compileSdk of at least 34. Note that updating a library or application's compileSdk (which allows newer APIs to be used) can be done separately from updating targetSdk (which opts the app in to new runtime behavior) and minSdk (which determines which devices the app can be installed on). 5. Dependency 'androidx.annotation:annotation-experimental:1.4.0' requires libraries and applications that depend on it to compile against version 34 or later of the Android APIs. :app is currently compiled against android-33. Also, the maximum recommended compile SDK version for Android Gradle plugin 8.0.0 is 33. Recommended action: Update this project's version of the Android Gradle plugin to one that supports 34, then update this project to use compileSdk of at least 34. Note that updating a library or application's compileSdk (which allows newer APIs to be used) can be done separately from updating targetSdk (which opts the app in to new runtime behavior) and minSdk (which determines which devices the app can be installed on). ============================================================================== 2: Task failed with an exception. ----------- * What went wrong: Execution failed for task ':app:mergeExtDexDebug'. > Could not resolve all files for configuration ':app:debugRuntimeClasspath'. > Failed to transform appcompat-resources-1.7.0.aar (androidx.appcompat:appcompat-resources:1.7.0) to match attributes {artifactType=android-dex, asm-transformed-variant=NONE, dexing-enable-desugaring=true, dexing-enable-jacoco-instrumentation=false, dexing-is-debuggable=true, dexing-min-sdk=24, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.libraryelements=aar, org.gradle.status=release, org.gradle.usage=java-runtime}. > Execution failed for DexingNoClasspathTransform: C:\Users\abc14\.gradle\caches\transforms-3\c494794d48d9429ce3837ff3d9162578\transformed\appcompat-resources-1.7.0-runtime.jar. > Error while dexing. > Failed to transform appcompat-1.7.0.aar (androidx.appcompat:appcompat:1.7.0) to match attributes {artifactType=android-dex, asm-transformed-variant=NONE, dexing-enable-desugaring=true, dexing-enable-jacoco-instrumentation=false, dexing-is-debuggable=true, dexing-min-sdk=24, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.libraryelements=aar, org.gradle.status=release, org.gradle.usage=java-runtime}. > Execution failed for DexingNoClasspathTransform: C:\Users\abc14\.gradle\caches\transforms-3\d251d80cfc588f74172158875c7b2196\transformed\appcompat-1.7.0-runtime.jar. > Error while dexing. * Try: > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. * Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeExtDexDebug'. Caused by: java.lang.NullPointerException: Cannot invoke "String.length()" because "<parameter1>" is null Caused by: java.util.concurrent.ExecutionException: com.android.tools.r8.utils.P0: java.lang.NullPointerException: Cannot invoke "String.length()" because "<parameter1>" is null Caused by: [CIRCULAR REFERENCE: java.lang.NullPointerException: Cannot invoke "String.length()" because "<parameter1>" is null] Cause 2: org.gradle.api.internal.artifacts.transform.TransformException: Failed to transform appcompat-1.7.0.aar (androidx.appcompat:appcompat:1.7.0) to match attributes {artifactType=android-dex, asm-transformed-variant=NONE, dexing-enable-desugaring=true, dexing-enable-jacoco-instrumentation=false, dexing-is-debuggable=true, dexing-min-sdk=24, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.libraryelements=aar, org.gradle.status=release, org.gradle.usage=java-runtime}. Caused by: org.gradle.api.internal.artifacts.transform.TransformException: Execution failed for DexingNoClasspathTransform: C:\Users\abc14\.gradle\caches\transforms-3\d251d80cfc588f74172158875c7b2196\transformed\appcompat-1.7.0-runtime.jar. Caused by: com.android.builder.dexing.DexArchiveBuilderException: Error while dexing. at com.android.builder.dexing.D8DexArchiveBuilder.getExceptionToRethrow(D8DexArchiveBuilder.java:189) Caused by: com.android.tools.r8.CompilationFailedException: Compilation failed to complete, origin: C:\Users\abc14\.gradle\caches\transforms-3\d251d80cfc588f74172158875c7b2196\transformed\appcompat-1.7.0-runtime.jar:androidx/appcompat/app/ActionBarDrawerToggle$1.class Caused by: java.lang.NullPointerException: Cannot invoke "String.length()" because "<parameter1>" is null Suppressed: java.lang.RuntimeException: java.util.concurrent.ExecutionException: com.android.tools.r8.utils.P0: java.lang.NullPointerException: Cannot invoke "String.length()" because "<parameter1>" is null Caused by: java.util.concurrent.ExecutionException: com.android.tools.r8.utils.P0: java.lang.NullPointerException: Cannot invoke "String.length()" because "<parameter1>" is null Caused by: com.android.tools.r8.utils.P0: java.lang.NullPointerException: Cannot invoke "String.length()" because "<parameter1>" is null Caused by: [CIRCULAR REFERENCE: java.lang.NullPointerException: Cannot invoke "String.length()" because "<parameter1>" is null]
[질문 내용] 여기에 질문 내용을 남겨주세요. 강의 11분쯤 insert 로그 확인 후 h2 db에 들어가 값이 들어가는지 확인을 하는데요 저도 로그에서 insert문 확인 후 h2 db에 들어 갔는데 값이 계속 안 나와 질문 올립니다. 밑에는 로그 내역이고 구글 드라이브 링크도 같이 올립니다. 2024-06-20T21:12:05.260+09:00 DEBUG 21664 --- [ Test worker] org.hibernate.SQL : select m1_0.member_id, m1_0.city, m1_0.street, m1_0.zipcode, m1_0.name from member m1_0 where m1_0.name=? 2024-06-20T21:12:05.276+09:00 INFO 21664 --- [ Test worker] p6spy : #1718885525275 | took 7ms | statement | connection 3| url jdbc:h2:mem:7cd22d26-ead4-4150-987b-79b62bd18ed5 select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.name=? select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.name='kim'; 2024-06-20T21:12:05.289+09:00 DEBUG 21664 --- [ Test worker] org.hibernate.SQL : select next value for member_seq 2024-06-20T21:12:05.292+09:00 INFO 21664 --- [ Test worker] p6spy : #1718885525292 | took 1ms | statement | connection 3| url jdbc:h2:mem:7cd22d26-ead4-4150-987b-79b62bd18ed5 select next value for member_seq select next value for member_seq; 2024-06-20T21:12:05.336+09:00 DEBUG 21664 --- [ Test worker] org.hibernate.SQL : insert into member (city, street, zipcode, name, member_id) values (?, ?, ?, ?, ?) 2024-06-20T21:12:05.340+09:00 INFO 21664 --- [ Test worker] p6spy : #1718885525340 | took 0ms | statement | connection 3| url jdbc:h2:mem:7cd22d26-ead4-4150-987b-79b62bd18ed5 insert into member (city,street,zipcode,name,member_id) values (?,?,?,?,?) insert into member (city,street,zipcode,name,member_id) values (NULL,NULL,NULL,'kim',1); 2024-06-20T21:12:05.345+09:00 INFO 21664 --- [ Test worker] p6spy : #1718885525345 | took 0ms | commit | connection 3| url jdbc:h2:mem:7cd22d26-ead4-4150-987b-79b62bd18ed5 ; 혼자 해결을 하고 싶었는데 가망이 없어 질문 올립니다.. 부탁드립니다!! ㅠㅠㅠㅠㅠ https://drive.google.com/file/d/1k4Dsk8P3O2Ofm0Ab-CyVTA98aN-66p1_/view?usp=drive_link
안녕하세요 영한님. 상속관계 Joined 매핑을 사용할 때, 부모테이블에 대하여 업데이트 쿼리 시 임시 테이블 Create Drop 에 대해 질문드리고 싶습니다. 최근에 플젝을 진행하면서 JPA 상속관계 Joined 전략을 활용했는데요, 프로젝트 초기에는 정규화된 테이블 구조로 먼저 진행하고, 추후 성능 이슈가 발생하면 단일 테이블 전략으로 역 정규화를 논의하는 것이 나을 것으로 판단했기 때문입니다. Domain // 부모 엔티티 @Entity @DiscriminatorColumn @Inheritance(strategy = InheritanceType.JOINED) public class Notification { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "notification_id") private Long id; @Enumerated(value = EnumType.STRING) @Column(nullable = false, columnDefinition = "varchar(50)") private NotificationEventType notificationEventType; @Column(nullable = false) private LocalDateTime createdAt; @Column(name = "\"read\"", nullable = false) private Boolean read; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) private User notifier; } // 자식 엔티티 @Entity public class RecruitmentNotification extends Notification { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "recruitment_id", nullable = false) private Recruitment actor; } @Entity public class StudyNotification extends Notification { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "study_id", nullable = false) private Study actor; } @Entity public class ReviewNotification extends Notification { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "review_id", nullable = false) private Review actor; } Service @Service @RequiredArgsConstructor @Slf4j public class NotificationCommandService { private final NotificationRepositoryImpl notificationRepository; public void updateNotificationsAsRead(final User user, final List<Long> notificationIds) { notificationRepository.updateNotificationsAsRead(user.getId(), notificationIds); } } Repository public interface NotificationJpaRepository extends JpaRepository<Notification, Long> { @Modifying @Query("UPDATE Notification n " + "SET n.read = true " + "WHERE n.notifier.id = :userId AND n.id IN :notificationIds") void updateNotificationsAsRead(final Long userId, final List<Long> notificationIds); } @Repository @RequiredArgsConstructor public class NotificationRepositoryImpl { private final JPAQueryFactory q; private final NotificationJpaRepository notificationJpaRepository; private final EntityManager em; public void updateNotificationsAsRead(final Long userId, final List<Long> notificationIds) { notificationJpaRepository.updateNotificationsAsRead(userId, notificationIds); em.flush(); em.clear(); } } 부모테이블에 대하여 업데이트 쿼리 시, JPA 구현체가 자체적으로 임시 테이블을 Create 및 Drop 하는 로그를 확인했습니다. create temporary table if not exists HT_notification(notification_id bigint not null, primary key (notification_id)) drop temporary table HT_notification 두 가지 문제점이 있다고 생각하는데요. 보안 이슈 등을 고려하여, 현재 상용 DB 의 백엔드 사용자 권한에 DDL을 제외하였습니다. 이에 따라 임시 테이블을 생성하지 못하고, 500 에러가 발생하는 상황입니다. JPA 상속 관계 매핑 전략만을 위해 DB 사용자 권한을 넓게 가져가는 것이 올바른지 잘 모르겠습니다 🤔 업데이트 API를 호출할 때마다, 임시 테이블을 생성하고 드랍하는 행위가 매우 비효율적 이라 생각되는데, 이럴 경우 Single 테이블 전략으로 수정하거나, 상속관계 매핑 자체를 안쓰는 방법밖엔 없을까요? 상속관계 매핑 전략은 애플리케이션 레벨에서 DB 테이블의 조작을 손쉽게하는 장점이 있긴하지만,결국 상용 서비스 중인 DB를 세팅할 땐 데이터베이스 레벨에서 DDL을 직접 세팅하는게 좋고, 기존의 장점이 상쇄되는 느낌입니다. 성능적 손해를 감수하면서도 상속 관계 매핑을 활용하는게 좋은 접근 방법인지 판단이 서지 않아 질문드립니다 🙂
안녕하세요 영한님. 상속관계 Joined 매핑을 사용할 때, 부모테이블에 대하여 업데이트 쿼리 시 임시 테이블 Create Drop 에 대해 질문드리고 싶습니다. 최근에 플젝을 진행하면서 JPA 상속관계 Joined 전략을 활용했습니다. 부모테이블에 대하여 업데이트 쿼리 시, JPA 구현체가 자체적으로 임시 테이블을 Create 및 Drop 하는 로그를 확인했습니다. Domain // 부모 엔티티 @Entity @DiscriminatorColumn @Inheritance(strategy = InheritanceType.JOINED) public class Notification { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "notification_id") private Long id; @Enumerated(value = EnumType.STRING) @Column(nullable = false, columnDefinition = "varchar(50)") private NotificationEventType notificationEventType; @Column(nullable = false) private LocalDateTime createdAt; @Column(name = "\"read\"", nullable = false) private Boolean read; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) private User notifier; } // 자식 엔티티 @Entity public class RecruitmentNotification extends Notification { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "recruitment_id", nullable = false) private Recruitment actor; } @Entity public class StudyNotification extends Notification { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "study_id", nullable = false) private Study actor; } @Entity public class ReviewNotification extends Notification { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "review_id", nullable = false) private Review actor; } Service @Service @RequiredArgsConstructor @Slf4j public class NotificationCommandService { private final NotificationRepositoryImpl notificationRepository; public void updateNotificationsAsRead(final User user, final List<Long> notificationIds) { notificationRepository.updateNotificationsAsRead(user.getId(), notificationIds); } } Repository public interface NotificationJpaRepository extends JpaRepository<Notification, Long> { @Modifying @Query("UPDATE Notification n " + "SET n.read = true " + "WHERE n.notifier.id = :userId AND n.id IN :notificationIds") void updateNotificationsAsRead(final Long userId, final List<Long> notificationIds); } @Repository @RequiredArgsConstructor public class NotificationRepositoryImpl { private final JPAQueryFactory q; private final NotificationJpaRepository notificationJpaRepository; private final EntityManager em; public void updateNotificationsAsRead(final Long userId, final List<Long> notificationIds) { notificationJpaRepository.updateNotificationsAsRead(userId, notificationIds); em.flush(); em.clear(); } } 업데이트 API를 호출할 때마다, 임시 테이블을 생성하고 드랍하는 행위가 매우 비효율적 이라 생각되는데, 이럴 경우 Single 테이블 전략으로 수정하거나, 상속관계 매핑 자체를 안쓰는 방법밖엔 없을까요? 상속관계 매핑 전략은 애플리케이션 레벨에서 DB 테이블의 조작을 손쉽게하는 장점이 있긴하지만, 결국 상용 서비스 중인 DB를 세팅할 땐 데이터베이스 레벨에서 DDL을 직접 세팅하는게 좋고, 기존의 장점이 상쇄되는 느낌입니다. 성능적 손해를 감수하면서도 상속 관계 매핑을 활용하는게 좋은 접근 방법인지 판단이 서지 않아 질문드립니다 🙂
자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
강의에서 사용자는 Id로 조회하고, 도서는 name으로 조회하는데 별도의 이유가 있을까요? 실제 구현한다면 동일한 도서명이 있을 것 같기도 하고, 일관성을 위해 강의를 참고하며 개인적으로 두가지 다 Id로 조회하도록 구현하고 있었습니다. Dto나 Repository 등에서 타입과 이름만 잘 변경해주면 문제가 없을꺼라고 생각했는데 중간에 제가 잘못 설계한 곳이 있는지 도서 대출시 BookRequestLoan에 값이 계속 안넘어옵니다. 혹시 Id (long 타입)로 조회하면 크게 달라지는 코드가 있거나 주의해야하는 부분이 있는지 여쭤보고 싶어서 문의글 남깁니다.
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 여러 서버에서 db에 접근할 경우 sequence전략의 인덱스 처리가 궁금합니다. allocationsize를 50으로 설정한 경우 a 서버에서 1~50까지 확보, 다음 인덱스번호 51번 (a서버에서 아직 종료되지 않음) b 서버에서 인덱스번호 요청 51번 반환, 51~100번 인덱스 사용 만약 해당 상황의 a서버에서 데이터를 3개 추가한 후 종료된다면 1,2,3번 인덱스만 사용되고 4~50번 인덱스는 앞으로 사용되지 않는건가요?? 그리고 여러 서버를 작동시키고 이러한 방식으로 사용한다면 중간중간 비어있는 인덱스가 많아질 것인데, 비어있는 인덱스는 재활용이 불가능한지 궁금합니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 메인 메서드 실행은 되는데 종료할때 아래와 같은 에러가 납니다. 찾아봐도 해결이 안되네요 도움 부탁드립니다 참고용으로 Build.gradle 소스도 함께 올립니다. plugins { id 'java' id 'org.springframework.boot' version '3.3.0' id 'io.spring.dependency-management' version '1.1.5' } group = 'jpabook' version = '0.0.1-SNAPSHOT' java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' // Validation (JSR-303 validation with Hibernate validator) 모듈을 꼭! 추가 implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-devtools'// compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' //JUnit4 추가 testImplementation("org.junit.vintage:junit-vintage-engine") { exclude group: "org.hamcrest", module: "hamcrest-core" } testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { useJUnitPlatform() }
실제로 코드를 치면 이렇게 형광펜처럼 경고 표시가 나오는데 강의 화면에서는 밑줄로만 표시되어서요! 혹시 설정을 따로 진행하신걸까요? ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요.
안녕하세요. 개인 프로젝트를 진행하다 이해가 안되는 부분이 있어서 질문드립니다. 맛집 서비스를 위한 REST API (HTTPS)를 구성하는 프로젝트로, 맛집 정보들은 DB를 사용하여 관리 REST API는 CRUD 연산을 제공 할 것입니다. 일단 프론트단을 제외하고 백만 개발한거라 @RestController를 사용해서 테스트를 끝냈는데, 이제 프론트까지 개발하려고 하니 @RestController는 json 형식으로 데이터를 받잖아요. 화면을 생성해야하는데 @RestController와 별개로 새로운 클래스를 생성하여 @Controller를 붙여 뷰단만 따로 관리하는 컨트롤러를 생성하는게 좋을까요? @RestController는 REST API를 관리하는 컨트롤러, @Controller는 화면단만 관리하는 컨트롤러로 각각 생성하는게 좋은건지 아니면 개발했던 @RestController에 ModelAndView를 활용하는 것 중 뭐가 더 나은건지? 궁금해요. 찾아보니 RestController에 화면을 줄때 자바스크립트나 ajax를 사용하는 방법이 있긴한데 보통 뭐를 더 사용하고 뭐가 더 좋은지 궁금합니다.
JPA에서는 데이터 타입을 톱레벨에서 2가지, 엔티티 타입과 값 타입으로 분류한다고 하는데 식별자도 값 타입 중 기본값 타입으로 분류되는 것이 맞나요? 예를 들어 Member 엔티티에 식별자인 memberId와 필드인 name, age가 있다면 memberId, name, age 모두 기본값 타입인 것인지 궁급합니다. 당연한 질문일 수도 있겠지만, 설명하실 때와 강의자료에서 모두 식별자가 기본값 타입이라는 언급을 안하시는 것 같아서 예외적인 부분인가 하여 질문합니다.