안녕하세요 질문있습니다.
미해결
Do it! 알고리즘 코딩테스트 with JAVA
방향 그래프 무방향 그래프에 따라서 자료구조에 자료를 저장하는 방법이 다르다고 하셨습니다. 그런데 지금 이 문제에서는 방향그래프 아닌가요?? 간선,엣지들을 보면 모두 방향이 있는 거 같은데, 왜 무방향그래프를 저장할 때처럼 arraylist에 값을 저장하는지 모르겠습니다.
- java
- 코딩-테스트
- 알고리즘
173만명의 커뮤니티!! 함께 토론해봐요.
미해결
Do it! 알고리즘 코딩테스트 with JAVA
방향 그래프 무방향 그래프에 따라서 자료구조에 자료를 저장하는 방법이 다르다고 하셨습니다. 그런데 지금 이 문제에서는 방향그래프 아닌가요?? 간선,엣지들을 보면 모두 방향이 있는 거 같은데, 왜 무방향그래프를 저장할 때처럼 arraylist에 값을 저장하는지 모르겠습니다.
미해결
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 스프링mvc2 강의에서 로그인처리2 - 스프링 인터셉터 요청 로그 강의에서 LogInterceptor 가 싱글톤처럼 사용된다고 했는데 왜 그런건가요?? 빈으로 등록이 안됐는데 어떻게 싱글톤으로 관리되는건가요??
미해결
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 업로드 할땐 new File() 을 다운로드와 조회할땐 new URLResouce()를 사용하셨는데 둘의 차이점이 뭔지 설명은 없어서요. 검색해봐도 명확한 답변이 안 나와 올려봅니다.
해결됨
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
======================================== [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 교재 '6장 스프링 MVC - 기본기능' 의 20페이지에서 @Conroller로 표기되어 있는데 혹시 @Controller 아닌가요?
해결됨
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
안녕하세요. 질문이 있어서 글을 올립니다. 게시글을 타임리프로 구현할 때, 게시글 상세화면에서 댓글들을 가져와야 하는 상황입니다. 댓글은 페이징이 필요합니다. 댓글 첫 페이지 부터 무조건 ajax로 만드는 게 맞는 건가요? 처음에는 최신 댓글 10개를 보여줄건데, 게시글상세 요청 -> 게시글 랜더링 -> ajax로 댓글 첫페이지 요청 게시글상세 요청 -> 게시글과 댓글첫페이지 랜더링 -> 댓글 두번째페이지부터 ajax로 요청 어느 방법이 맞는 건가요?
미해결
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. public FrontControllerServletV1() { // 해쉬맵은 키와 값으로 저장됨 => URI는 키, 객체는 값임 controllerV1Map.put("/front-controller/v1/members/new-form", new MemberFormControllerV1()); controllerV1Map.put("/front-controller/v1/members/save", new MemberSaveControllerV1()); controllerV1Map.put("/front-controller/v1/members", new MemberListControllerV1()); } WEB-INF는 외부에서 들어오지 못하니 webapp 폴더 밑에 jsp 폴더 안에 있는 파일로 먼저 호출한 다음 컨트롤러로 WEB-INF 하위 파일들을 RequestDispatcher 객체을 통해 서버 단에서 이동하는 게 맞나요?
미해결
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
return new ResponseEntity<>("OK",HttpStatus.OK); // response.setStatus(200); 위 두개가 무슨 차이 인가요??
미해결
스프링 프레임워크는 내 손에 [스프2탄]
8강 스프2탄_Junit리스트보기 Controller테스트 강의 중 질문입니다. 테스트코드 BoardControllerTest.java에서 @Test public void testList() throws Exception{ log.info ( mockMvc.perform(MockMvcRequestBuilders. get ("/board/list")) .andReturn() .getModelAndView().getModelMap()); } 굵은 글씨 get이라고 하셨는데 BoardController.java에서 @GetMapping ("/list") public String getList(Model model) { List<Board> list=boardService.getList(); // 객체바인딩 model.addAttribute("list",list); return "board/boardList"; } 굵은 글씨 @GetMapping 이라고 해줘서 테스트코드에서 get인 것은 알겠는데 왜 get이라고 해 줬는데 이해가 잘 안되서요.. 특별한 거 없으면 그냥 get이라고 해주면 되는 건가요? 두번째 질문은 다음 강의 언제 나오나요
미해결
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 스프링 MVC 1편 - 회원 관리 웹 애플리케이션 요구사항 강의를 듣다 질문이 생깁니다. 이 때 test를 하면서 MemberRepository를 싱글톤으로 유지한다 하셨는데 테스트 코드에서 바로 MemberRepository.getInstance를 사용할 수 있는 이유가 MemberRepository 클래스에서 static으로 new를 해서 맞나요?? 제 이해로는 코드가 실행이 되면 모든 static 부분 코드를 읽어 실행하는데 이 때 new MemberRepository가 실행되어 객체가 생성되었다 이해했습니다. 제 이해가 맞을까요?
미해결
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx ) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG ) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 네 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 네 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 네 [질문 내용] 여기에 질문 내용을 남겨주세요. Item 도메인 객체 대신 폼 데이터 전달을 위해서 ItemSaveForm으로 교체해서 사용을 했는데 Post요청으로 폼 데이터 불러오는 부분 말고 Get요청으로 상품 추가 폼 불러오는 부분에서 model.addAttribute("item", new Item()); 대신 model.addAttribute("item", new ItemSaveForm()); 으로 변경해야 하는 것이 아닌지 궁금합니다! 이 부분에 대한 언급이 없으셔서 혹시 바꾸지 않은 특별한 이유가 있으실까요?
미해결
스프링 프레임워크는 내 손에 [스프1탄]
현재 스프1탄 mvc01버전 듣고 있는데 hikari관련 오류가 나서 깃허브가서 소스코드를 가져오려고 합니다. 깃 들어가니 레포지토리가 정리가 잘 안되어있어서 찾지를 못하겠는데 어떤 레포지토리를 봐야하나요???
해결됨
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 위 그림과 같이 전송한 데이터를 다 볼 수 있는데 만약 민감한 데이터를 전송하는 경우에는 어떤 방식으로 전송을 하게 되나요?
미해결
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 스프링 mvc 강의듣다 의문이 들어서 그러는데요 서버 시작하고 인터넷띄어서 예를 들어 localhost:8080/index.html 이런 식으로 접근할때 서버는 resources/static 아래에 있는 index.html 을 보여주는 건가요 아님 resources/template 아래에 있는 index.html 을 보여주는 건가요?? 만약에 static 이나 template 아래에 같은 이름의 파일이 있다면 static 아래에 있는 파일을 보여주나요 아님 template 아래에 있는 파일을 보여주나요?
미해결
자바 ORM 표준 JPA 프로그래밍 - 기본편
실전 예제 4를 하고 있는데 create로 설정하면 메인메서드 실행할 때마다 테이블 드랍되고 실행되어야하는데 아래와 같은 오류가 자꾸 발생하면서 실행이 안되는데 왜그럴까요 ㅠㅠ 수동으로 데이터베이스에서 드랍하고 실행하거나 update 등으로만 설정해야 잘 작동되는데 왜그럴까요... /Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=49362:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/hwang-gyuhyeog/Desktop/JPA/1.자바 ORM 표준 JPA 프로그래밍-기본편/jpashop/target/classes:/Users/hwang-gyuhyeog/.m2/repository/org/hibernate/hibernate-entitymanager/5.3.10.Final/hibernate-entitymanager-5.3.10.Final.jar:/Users/hwang-gyuhyeog/.m2/repository/org/jboss/logging/jboss-logging/3.3.2.Final/jboss-logging-3.3.2.Final.jar:/Users/hwang-gyuhyeog/.m2/repository/org/hibernate/hibernate-core/5.3.10.Final/hibernate-core-5.3.10.Final.jar:/Users/hwang-gyuhyeog/.m2/repository/org/javassist/javassist/3.23.2-GA/javassist-3.23.2-GA.jar:/Users/hwang-gyuhyeog/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/Users/hwang-gyuhyeog/.m2/repository/org/jboss/jandex/2.0.5.Final/jandex-2.0.5.Final.jar:/Users/hwang-gyuhyeog/.m2/repository/com/fasterxml/classmate/1.3.4/classmate-1.3.4.jar:/Users/hwang-gyuhyeog/.m2/repository/javax/activation/javax.activation-api/1.2.0/javax.activation-api-1.2.0.jar:/Users/hwang-gyuhyeog/.m2/repository/org/dom4j/dom4j/2.1.1/dom4j-2.1.1.jar:/Users/hwang-gyuhyeog/.m2/repository/org/hibernate/common/hibernate-commons-annotations/5.0.4.Final/hibernate-commons-annotations-5.0.4.Final.jar:/Users/hwang-gyuhyeog/.m2/repository/javax/persistence/javax.persistence-api/2.2/javax.persistence-api-2.2.jar:/Users/hwang-gyuhyeog/.m2/repository/net/bytebuddy/byte-buddy/1.9.5/byte-buddy-1.9.5.jar:/Users/hwang-gyuhyeog/.m2/repository/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.1.1.Final/jboss-transaction-api_1.2_spec-1.1.1.Final.jar:/Users/hwang-gyuhyeog/.m2/repository/com/h2database/h2/1.4.200/h2-1.4.200.jar:/Users/hwang-gyuhyeog/.m2/repository/javax/xml/bind/jaxb-api/2.3.0/jaxb-api-2.3.0.jar jpabook.jpashop.JpaMain 8월 08, 2023 10:39:56 오후 org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation INFO: HHH000204: Processing PersistenceUnitInfo [ name: hello ...] 8월 08, 2023 10:39:56 오후 org.hibernate.Version logVersion INFO: HHH000412: Hibernate Core { 5.3.10.Final } 8월 08, 2023 10:39:56 오후 org.hibernate.cfg.Environment <clinit> INFO: HHH000206: hibernate.properties not found 8월 08, 2023 10:39:57 오후 org.hibernate.annotations.common.reflection.java .JavaReflectionManager <clinit> INFO: HCANN000001: Hibernate Commons Annotations { 5.0.4.Final } 8월 08, 2023 10:39:57 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!) 8월 08, 2023 10:39:57 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001005: using driver [org.h2.Driver] at URL [jdbc:h2:tcp:// localhost/~/jpashop ] 8월 08, 2023 10:39:57 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001001: Connection properties: {user=sa} 8월 08, 2023 10:39:57 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001003: Autocommit mode: false 8월 08, 2023 10:39:57 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init> INFO: HHH000115: Hibernate connection pool size: 20 (min=1) 8월 08, 2023 10:39:57 오후 org.hibernate.dialect.Dialect <init> INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect Hibernate: drop table Category if exists Hibernate: drop table CATEGORY_ITEM if exists Hibernate: drop table Delivery if exists Hibernate: drop table Item if exists Hibernate: drop table Member if exists Hibernate: drop table OrderItem if exists Hibernate: drop table ORDERS if exists Hibernate: drop sequence if exists hibernate_sequence Hibernate: create sequence hibernate_sequence start with 1 increment by 1 8월 08, 2023 10:39:57 오후 org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@7f5b9db] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode. 8월 08, 2023 10:39:57 오후 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Error executing DDL " drop table Category if exists" via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " drop table Category if exists" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:67 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlString( SchemaDropperImpl.java:375 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlStrings( SchemaDropperImpl.java:359 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.dropFromMetadata( SchemaDropperImpl.java:241 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.performDrop( SchemaDropperImpl.java:154 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop( SchemaDropperImpl.java:126 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop( SchemaDropperImpl.java:112 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction( SchemaManagementToolCoordinator.java:144 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process( SchemaManagementToolCoordinator.java:72 ) at org.hibernate.internal.SessionFactoryImpl.<init>( SessionFactoryImpl.java:310 ) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build ( SessionFactoryBuilderImpl.java:467 ) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build ( EntityManagerFactoryBuilderImpl.java:939 ) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory( HibernatePersistenceProvider.java:56 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:79 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:54 ) at jpabook.jpashop.JpaMain.main( JpaMain.java:14 ) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Cannot drop "CATEGORY" because "FKJIP0OR3VEMIXCCL6VX0KLUJ03" depends on it; SQL statement: drop table Category if e [90107-214] at org.h2.message.DbException.getJdbcSQLException( DbException.java:632 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:477 ) at org.h2.message.DbException.get( DbException.java:223 ) at org.h2.command.ddl.DropTable.prepareDrop( DropTable.java:97 ) at org.h2.command.ddl.DropTable.update( DropTable.java:121 ) at org.h2.command.CommandContainer.update( CommandContainer.java:169 ) at org.h2.command.Command.executeUpdate( Command.java:252 ) at org.h2.server.TcpServerThread.process( TcpServerThread.java:408 ) at org.h2.server.TcpServerThread.run ( TcpServerThread.java:191 ) at java.base/java.lang.Thread.run( Thread.java:834 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:576 ) at org.h2.engine.SessionRemote.done( SessionRemote.java:611 ) at org.h2.command.CommandRemote.executeUpdate( CommandRemote.java:237 ) at org.h2.jdbc.JdbcStatement.executeInternal( JdbcStatement.java:228 ) at org.h2.jdbc.JdbcStatement.execute( JdbcStatement.java:201 ) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:54 ) ... 15 more 8월 08, 2023 10:39:57 오후 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Error executing DDL " drop table Delivery if exists" via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " drop table Delivery if exists" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:67 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlString( SchemaDropperImpl.java:375 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlStrings( SchemaDropperImpl.java:359 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.dropFromMetadata( SchemaDropperImpl.java:241 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.performDrop( SchemaDropperImpl.java:154 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop( SchemaDropperImpl.java:126 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop( SchemaDropperImpl.java:112 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction( SchemaManagementToolCoordinator.java:144 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process( SchemaManagementToolCoordinator.java:72 ) at org.hibernate.internal.SessionFactoryImpl.<init>( SessionFactoryImpl.java:310 ) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build ( SessionFactoryBuilderImpl.java:467 ) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build ( EntityManagerFactoryBuilderImpl.java:939 ) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory( HibernatePersistenceProvider.java:56 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:79 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:54 ) at jpabook.jpashop.JpaMain.main( JpaMain.java:14 ) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Cannot drop "DELIVERY" because "FKDBS21F1YI0COXY9Y0KXW4G9JF" depends on it; SQL statement: drop table Delivery if e [90107-214] at org.h2.message.DbException.getJdbcSQLException( DbException.java:632 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:477 ) at org.h2.message.DbException.get( DbException.java:223 ) at org.h2.command.ddl.DropTable.prepareDrop( DropTable.java:97 ) at org.h2.command.ddl.DropTable.update( DropTable.java:121 ) at org.h2.command.CommandContainer.update( CommandContainer.java:169 ) at org.h2.command.Command.executeUpdate( Command.java:252 ) at org.h2.server.TcpServerThread.process( TcpServerThread.java:408 ) at org.h2.server.TcpServerThread.run ( TcpServerThread.java:191 ) at java.base/java.lang.Thread.run( Thread.java:834 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:576 ) at org.h2.engine.SessionRemote.done( SessionRemote.java:611 ) at org.h2.command.CommandRemote.executeUpdate( CommandRemote.java:237 ) at org.h2.jdbc.JdbcStatement.executeInternal( JdbcStatement.java:228 ) at org.h2.jdbc.JdbcStatement.execute( JdbcStatement.java:201 ) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:54 ) ... 15 more 8월 08, 2023 10:39:57 오후 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Error executing DDL " drop table Item if exists" via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " drop table Item if exists" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:67 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlString( SchemaDropperImpl.java:375 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlStrings( SchemaDropperImpl.java:359 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.dropFromMetadata( SchemaDropperImpl.java:241 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.performDrop( SchemaDropperImpl.java:154 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop( SchemaDropperImpl.java:126 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop( SchemaDropperImpl.java:112 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction( SchemaManagementToolCoordinator.java:144 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process( SchemaManagementToolCoordinator.java:72 ) at org.hibernate.internal.SessionFactoryImpl.<init>( SessionFactoryImpl.java:310 ) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build ( SessionFactoryBuilderImpl.java:467 ) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build ( EntityManagerFactoryBuilderImpl.java:939 ) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory( HibernatePersistenceProvider.java:56 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:79 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:54 ) at jpabook.jpashop.JpaMain.main( JpaMain.java:14 ) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Cannot drop "ITEM" because "FK75MRPPRV8OIGH00Y92TIBW7ID, FK2SRBE8WJBANR4VTKRSB8ATQ7O, FKQQWSWM36Y8UQOH9EMTORUOXCV, FKABGE9EQALSPCEJIJ53RAT7PJH" depends on it; SQL statement: drop table Item if e [90107-214] at org.h2.message.DbException.getJdbcSQLException( DbException.java:632 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:477 ) at org.h2.message.DbException.get( DbException.java:223 ) at org.h2.command.ddl.DropTable.prepareDrop( DropTable.java:97 ) at org.h2.command.ddl.DropTable.update( DropTable.java:121 ) at org.h2.command.CommandContainer.update( CommandContainer.java:169 ) at org.h2.command.Command.executeUpdate( Command.java:252 ) at org.h2.server.TcpServerThread.process( TcpServerThread.java:408 ) at org.h2.server.TcpServerThread.run ( TcpServerThread.java:191 ) at java.base/java.lang.Thread.run( Thread.java:834 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:576 ) at org.h2.engine.SessionRemote.done( SessionRemote.java:611 ) at org.h2.command.CommandRemote.executeUpdate( CommandRemote.java:237 ) at org.h2.jdbc.JdbcStatement.executeInternal( JdbcStatement.java:228 ) at org.h2.jdbc.JdbcStatement.execute( JdbcStatement.java:201 ) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:54 ) ... 15 more 8월 08, 2023 10:39:57 오후 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Error executing DDL " drop table Member if exists" via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " drop table Member if exists" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:67 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlString( SchemaDropperImpl.java:375 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlStrings( SchemaDropperImpl.java:359 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.dropFromMetadata( SchemaDropperImpl.java:241 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.performDrop( SchemaDropperImpl.java:154 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop( SchemaDropperImpl.java:126 ) at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop( SchemaDropperImpl.java:112 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction( SchemaManagementToolCoordinator.java:144 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process( SchemaManagementToolCoordinator.java:72 ) at org.hibernate.internal.SessionFactoryImpl.<init>( SessionFactoryImpl.java:310 ) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build ( SessionFactoryBuilderImpl.java:467 ) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build ( EntityManagerFactoryBuilderImpl.java:939 ) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory( HibernatePersistenceProvider.java:56 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:79 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:54 ) at jpabook.jpashop.JpaMain.main( JpaMain.java:14 ) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Cannot drop "MEMBER" because "FKH0DB7KQR88ED8HQTCQW3JKCIA" depends on it; SQL statement: drop table Member if e [90107-214] at org.h2.message.DbException.getJdbcSQLException( DbException.java:632 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:477 ) at org.h2.message.DbException.get( DbException.java:223 ) at org.h2.command.ddl.DropTable.prepareDrop( DropTable.java:97 ) at org.h2.command.ddl.DropTable.update( DropTable.java:121 ) at org.h2.command.CommandContainer.update( CommandContainer.java:169 ) at org.h2.command.Command.executeUpdate( Command.java:252 ) at org.h2.server.TcpServerThread.process( TcpServerThread.java:408 ) at org.h2.server.TcpServerThread.run ( TcpServerThread.java:191 ) at java.base/java.lang.Thread.run( Thread.java:834 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:576 ) at org.h2.engine.SessionRemote.done( SessionRemote.java:611 ) at org.h2.command.CommandRemote.executeUpdate( CommandRemote.java:237 ) at org.h2.jdbc.JdbcStatement.executeInternal( JdbcStatement.java:228 ) at org.h2.jdbc.JdbcStatement.execute( JdbcStatement.java:201 ) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:54 ) ... 15 more 8월 08, 2023 10:39:57 오후 org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@5c723f2d] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode. 8월 08, 2023 10:39:57 오후 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Error executing DDL " create table Category ( id bigint not null, name varchar(255), PARENT_ID bigint, primary key (id) )" via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " create table Category ( id bigint not null, name varchar(255), PARENT_ID bigint, primary key (id) )" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:67 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString( SchemaCreatorImpl.java:440 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings( SchemaCreatorImpl.java:424 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata( SchemaCreatorImpl.java:315 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation( SchemaCreatorImpl.java:166 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation( SchemaCreatorImpl.java:135 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation( SchemaCreatorImpl.java:121 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction( SchemaManagementToolCoordinator.java:155 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process( SchemaManagementToolCoordinator.java:72 ) at org.hibernate.internal.SessionFactoryImpl.<init>( SessionFactoryImpl.java:310 ) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build ( SessionFactoryBuilderImpl.java:467 ) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build ( EntityManagerFactoryBuilderImpl.java:939 ) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory( HibernatePersistenceProvider.java:56 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:79 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:54 ) at jpabook.jpashop.JpaMain.main( JpaMain.java:14 ) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "CATEGORY" already exists; SQL statement: create table Category ( id bigint not null, name varchar(255), PARENT_ID bigint, primary key (id) [42101-214] at org.h2.message.DbException.getJdbcSQLException( DbException.java:502 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:477 ) at org.h2.message.DbException.get( DbException.java:223 ) at org.h2.message.DbException.get( DbException.java:199 ) at org.h2.command.ddl.CreateTable.update( CreateTable.java:91 ) at org.h2.command.CommandContainer.update( CommandContainer.java:169 ) at org.h2.command.Command.executeUpdate( Command.java:252 ) at org.h2.server.TcpServerThread.process( TcpServerThread.java:408 ) at org.h2.server.TcpServerThread.run ( TcpServerThread.java:191 ) at java.base/java.lang.Thread.run( Thread.java:834 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:453 ) at org.h2.engine.SessionRemote.done( SessionRemote.java:611 ) at org.h2.command.CommandRemote.executeUpdate( CommandRemote.java:237 ) at org.h2.jdbc.JdbcStatement.executeInternal( JdbcStatement.java:228 ) at org.h2.jdbc.JdbcStatement.execute( JdbcStatement.java:201 ) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:54 ) ... 15 more 8월 08, 2023 10:39:57 오후 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Error executing DDL " create table Delivery ( id bigint not null, city varchar(255), deliveryStatus integer, street varchar(255), zipcode varchar(255), primary key (id) )" via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " create table Delivery ( id bigint not null, city varchar(255), deliveryStatus integer, street varchar(255), zipcode varchar(255), primary key (id) )" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:67 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString( SchemaCreatorImpl.java:440 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings( SchemaCreatorImpl.java:424 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata( SchemaCreatorImpl.java:315 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation( SchemaCreatorImpl.java:166 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation( SchemaCreatorImpl.java:135 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation( SchemaCreatorImpl.java:121 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction( SchemaManagementToolCoordinator.java:155 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process( SchemaManagementToolCoordinator.java:72 ) at org.hibernate.internal.SessionFactoryImpl.<init>( SessionFactoryImpl.java:310 ) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build ( SessionFactoryBuilderImpl.java:467 ) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build ( EntityManagerFactoryBuilderImpl.java:939 ) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory( HibernatePersistenceProvider.java:56 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:79 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:54 ) at jpabook.jpashop.JpaMain.main( JpaMain.java:14 ) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "DELIVERY" already exists; SQL statement: create table Delivery ( id bigint not null, city varchar(255), deliveryStatus integer, street varchar(255), zipcode varchar(255), primary key (id) [42101-214] at org.h2.message.DbException.getJdbcSQLException( DbException.java:502 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:477 ) at org.h2.message.DbException.get( DbException.java:223 ) at org.h2.message.DbException.get( DbException.java:199 ) at org.h2.command.ddl.CreateTable.update( CreateTable.java:91 ) at org.h2.command.CommandContainer.update( CommandContainer.java:169 ) at org.h2.command.Command.executeUpdate( Command.java:252 ) at org.h2.server.TcpServerThread.process( TcpServerThread.java:408 ) at org.h2.server.TcpServerThread.run ( TcpServerThread.java:191 ) at java.base/java.lang.Thread.run( Thread.java:834 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:453 ) at org.h2.engine.SessionRemote.done( SessionRemote.java:611 ) at org.h2.command.CommandRemote.executeUpdate( CommandRemote.java:237 ) at org.h2.jdbc.JdbcStatement.executeInternal( JdbcStatement.java:228 ) at org.h2.jdbc.JdbcStatement.execute( JdbcStatement.java:201 ) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:54 ) ... 15 more 8월 08, 2023 10:39:57 오후 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Error executing DDL " create table Item ( DTYPE varchar(31) not null, ITEM_ID bigint not null, name varchar(255), price integer not null, stockQuantity integer not null, actor varchar(255), director varchar(255), author varchar(255), isbn varchar(255), artist varchar(255), etc varchar(255), primary key (ITEM_ID) )" via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " create table Item ( DTYPE varchar(31) not null, ITEM_ID bigint not null, name varchar(255), price integer not null, stockQuantity integer not null, actor varchar(255), director varchar(255), author varchar(255), isbn varchar(255), artist varchar(255), etc varchar(255), primary key (ITEM_ID) )" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:67 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString( SchemaCreatorImpl.java:440 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings( SchemaCreatorImpl.java:424 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata( SchemaCreatorImpl.java:315 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation( SchemaCreatorImpl.java:166 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation( SchemaCreatorImpl.java:135 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation( SchemaCreatorImpl.java:121 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction( SchemaManagementToolCoordinator.java:155 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process( SchemaManagementToolCoordinator.java:72 ) at org.hibernate.internal.SessionFactoryImpl.<init>( SessionFactoryImpl.java:310 ) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build ( SessionFactoryBuilderImpl.java:467 ) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build ( EntityManagerFactoryBuilderImpl.java:939 ) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory( HibernatePersistenceProvider.java:56 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:79 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:54 ) at jpabook.jpashop.JpaMain.main( JpaMain.java:14 ) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ITEM" already exists; SQL statement: create table Item ( DTYPE varchar(31) not null, ITEM_ID bigint not null, name varchar(255), price integer not null, stockQuantity integer not null, actor varchar(255), director varchar(255), author varchar(255), isbn varchar(255), artist varchar(255), etc varchar(255), primary key (ITEM_ID) [42101-214] at org.h2.message.DbException.getJdbcSQLException( DbException.java:502 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:477 ) at org.h2.message.DbException.get( DbException.java:223 ) at org.h2.message.DbException.get( DbException.java:199 ) at org.h2.command.ddl.CreateTable.update( CreateTable.java:91 ) at org.h2.command.CommandContainer.update( CommandContainer.java:169 ) at org.h2.command.Command.executeUpdate( Command.java:252 ) at org.h2.server.TcpServerThread.process( TcpServerThread.java:408 ) at org.h2.server.TcpServerThread.run ( TcpServerThread.java:191 ) at java.base/java.lang.Thread.run( Thread.java:834 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:453 ) at org.h2.engine.SessionRemote.done( SessionRemote.java:611 ) at org.h2.command.CommandRemote.executeUpdate( CommandRemote.java:237 ) at org.h2.jdbc.JdbcStatement.executeInternal( JdbcStatement.java:228 ) at org.h2.jdbc.JdbcStatement.execute( JdbcStatement.java:201 ) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:54 ) ... 15 more 8월 08, 2023 10:39:57 오후 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Error executing DDL " create table Member ( MEMBER_ID bigint not null, city varchar(255), name varchar(255), street varchar(255), zipcode varchar(255), primary key (MEMBER_ID) )" via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " create table Member ( MEMBER_ID bigint not null, city varchar(255), name varchar(255), street varchar(255), zipcode varchar(255), primary key (MEMBER_ID) )" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:67 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString( SchemaCreatorImpl.java:440 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings( SchemaCreatorImpl.java:424 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata( SchemaCreatorImpl.java:315 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation( SchemaCreatorImpl.java:166 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation( SchemaCreatorImpl.java:135 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation( SchemaCreatorImpl.java:121 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction( SchemaManagementToolCoordinator.java:155 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process( SchemaManagementToolCoordinator.java:72 ) at org.hibernate.internal.SessionFactoryImpl.<init>( SessionFactoryImpl.java:310 ) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build ( SessionFactoryBuilderImpl.java:467 ) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build ( EntityManagerFactoryBuilderImpl.java:939 ) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory( HibernatePersistenceProvider.java:56 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:79 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:54 ) at jpabook.jpashop.JpaMain.main( JpaMain.java:14 ) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "MEMBER" already exists; SQL statement: create table Member ( MEMBER_ID bigint not null, city varchar(255), name varchar(255), street varchar(255), zipcode varchar(255), primary key (MEMBER_ID) [42101-214] at org.h2.message.DbException.getJdbcSQLException( DbException.java:502 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:477 ) at org.h2.message.DbException.get( DbException.java:223 ) at org.h2.message.DbException.get( DbException.java:199 ) at org.h2.command.ddl.CreateTable.update( CreateTable.java:91 ) at org.h2.command.CommandContainer.update( CommandContainer.java:169 ) at org.h2.command.Command.executeUpdate( Command.java:252 ) at org.h2.server.TcpServerThread.process( TcpServerThread.java:408 ) at org.h2.server.TcpServerThread.run ( TcpServerThread.java:191 ) at java.base/java.lang.Thread.run( Thread.java:834 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:453 ) at org.h2.engine.SessionRemote.done( SessionRemote.java:611 ) at org.h2.command.CommandRemote.executeUpdate( CommandRemote.java:237 ) at org.h2.jdbc.JdbcStatement.executeInternal( JdbcStatement.java:228 ) at org.h2.jdbc.JdbcStatement.execute( JdbcStatement.java:201 ) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:54 ) ... 15 more 8월 08, 2023 10:39:57 오후 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Error executing DDL " alter table Category add constraint FK8tepc1qkmluodspg6tnliwhit foreign key (PARENT_ID) references Category" via JDBC Statement org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " alter table Category add constraint FK8tepc1qkmluodspg6tnliwhit foreign key (PARENT_ID) references Category" via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:67 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString( SchemaCreatorImpl.java:440 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings( SchemaCreatorImpl.java:424 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata( SchemaCreatorImpl.java:375 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation( SchemaCreatorImpl.java:166 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation( SchemaCreatorImpl.java:135 ) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation( SchemaCreatorImpl.java:121 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction( SchemaManagementToolCoordinator.java:155 ) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process( SchemaManagementToolCoordinator.java:72 ) at org.hibernate.internal.SessionFactoryImpl.<init>( SessionFactoryImpl.java:310 ) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build ( SessionFactoryBuilderImpl.java:467 ) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build ( EntityManagerFactoryBuilderImpl.java:939 ) at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory( HibernatePersistenceProvider.java:56 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:79 ) at javax.persistence.Persistence.createEntityManagerFactory( Persistence.java:54 ) at jpabook.jpashop.JpaMain.main( JpaMain.java:14 ) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Constraint "FK8TEPC1QKMLUODSPG6TNLIWHIT" already exists; SQL statement: alter table Category add constraint FK8tepc1qkmluodspg6tnliwhit foreign key (PARENT_ID) references Cat [90045-214] at org.h2.message.DbException.getJdbcSQLException( DbException.java:632 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:477 ) at org.h2.message.DbException.get( DbException.java:223 ) at org.h2.message.DbException.get( DbException.java:199 ) at org.h2.command.ddl.AlterTableAddConstraint.tryUpdate( AlterTableAddConstraint.java:109 ) at org.h2.command.ddl.AlterTableAddConstraint.update( AlterTableAddConstraint.java:72 ) at org.h2.command.ddl.AlterTable.update( AlterTable.java:46 ) at org.h2.command.CommandContainer.update( CommandContainer.java:169 ) at org.h2.command.Command.executeUpdate( Command.java:252 ) at org.h2.server.TcpServerThread.process( TcpServerThread.java:408 ) at org.h2.server.TcpServerThread.run ( TcpServerThread.java:191 ) at java.base/java.lang.Thread.run( Thread.java:834 ) at org.h2.message.DbException.getJdbcSQLException( DbException.java:576 ) at org.h2.engine.SessionRemote.done( SessionRemote.java:611 ) at org.h2.command.CommandRemote.executeUpdate( CommandRemote.java:237 ) at org.h2.jdbc.JdbcStatement.executeInternal( JdbcStatement.java:228 ) at org.h2.jdbc.JdbcStatement.execute( JdbcStatement.java:201 ) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept( GenerationTargetToDatabase.java:54 ) ... 15 more Hibernate: create table Category ( id bigint not null, name varchar(255), PARENT_ID bigint, primary key (id) ) Hibernate: create table CATEGORY_ITEM ( CATEGORY_ID bigint not null, ITEM_ID bigint not null ) Hibernate: create table Delivery ( id bigint not null, city varchar(255), deliveryStatus integer, street varchar(255), zipcode varchar(255), primary key (id) ) Hibernate: create table Item ( DTYPE varchar(31) not null, ITEM_ID bigint not null, name varchar(255), price integer not null, stockQuantity integer not null, actor varchar(255), director varchar(255), author varchar(255), isbn varchar(255), artist varchar(255), etc varchar(255), primary key (ITEM_ID) ) Hibernate: create table Member ( MEMBER_ID bigint not null, city varchar(255), name varchar(255), street varchar(255), zipcode varchar(255), primary key (MEMBER_ID) ) Hibernate: create table OrderItem ( ORDER_ITEM_ID bigint not null, ITEM_ID bigint, ORDER_ID bigint, primary key (ORDER_ITEM_ID) ) Hibernate: create table ORDERS ( ORDER_ID bigint not null, orderDate timestamp, status varchar(255), DELIVERY_ID bigint, MEMBER_ID bigint, primary key (ORDER_ID) ) Hibernate: alter table Category add constraint FK8tepc1qkmluodspg6tnliwhit foreign key (PARENT_ID) references Category Hibernate: alter table CATEGORY_ITEM add constraint FKf1uerpnmn49vl1spbbplgxaun foreign key (ITEM_ID) references Item Hibernate: alter table CATEGORY_ITEM add constraint FKjip0or3vemixccl6vx0kluj03 foreign key (CATEGORY_ID) references Category Hibernate: alter table OrderItem add constraint FKabge9eqalspcejij53rat7pjh foreign key (ITEM_ID) references Item Hibernate: alter table OrderItem add constraint FKk7lmf97wukpquk6d8blxy5neq foreign key (ORDER_ID) references ORDERS Hibernate: alter table ORDERS add constraint FKdbs21f1yi0coxy9y0kxw4g9jf foreign key (DELIVERY_ID) references Delivery Hibernate: alter table ORDERS add constraint FKh0db7kqr88ed8hqtcqw3jkcia foreign key (MEMBER_ID) references Member 8월 08, 2023 10:39:57 오후 org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@30f74e79' Hibernate: call next value for hibernate_sequence Hibernate: /* insert jpabook.jpashop.domain.Book */ insert into Item (name, price, stockQuantity, author, isbn, DTYPE, ITEM_ID) values (?, ?, ?, ?, ?, 'Book', ?) 8월 08, 2023 10:39:57 오후 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions WARN: SQL Error: 23505, SQLState: 23505 8월 08, 2023 10:39:57 오후 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions ERROR: Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.ITEM(ITEM_ID) ( /* key:1 */ 'Book', CAST(1 AS BIGINT), 'dd', 0, 0, NULL, NULL, 'abc', NULL, NULL, NULL)"; SQL statement: /* insert jpabook.jpashop.domain.Book */ insert into Item (name, price, stockQuantity, author, isbn, DTYPE, I [23505-200] 8월 08, 2023 10:39:57 오후 org.hibernate.internal.ExceptionMapperStandardImpl mapManagedFlushFailure ERROR: HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement] 8월 08, 2023 10:39:57 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop INFO: HHH10001008: Cleaning up connection pool [jdbc:h2:tcp:// localhost/~/jpashop ] Process finished with exit code 0
미해결
스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 해당 강의 52초 경에 MemberService.java클래스에서 private final MemberRepository memberRepository; public MemberService(MemberRepository memberRepository) { this.memberRepository = memberRepository; } //어노테이션은 지웠습니다. 이부분에서 public MemberService(MemberRepository memberRepository) 이 괄호안에 매개변수가 MemoryMemberRepository가 되어야 하는게 아닌가요? 제가 저기를 MemoryMemberRepository로 진행을 하고 있더라구요. 그래서 에러가 떳었는데 왜 MemberRepository인지 궁금합니다.
미해결
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
제가 공부하면서 주석으로 정리한 것 있는데 하찮은 실력이지만 다른 공부하시는 분들께 도움이 될 수 있을까 해서 공부한 내용을 올려봅니다! 범위는 "셀렉트박스"까지 내용입니다! addForm.html <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <link th:href="@{/css/bootstrap.min.css}" href="../css/bootstrap.min.css" rel="stylesheet"> <style> .container { max-width: 560px; } </style> </head> <body> <div class="container"> <div class="py-5 text-center"> <h2>상품 등록 폼</h2> </div> <form action="item.html" th:action method="post" th:object="${item}"> <!-- items.html 에서 상품 등록 버튼을 누름 : th:onclick="|location.href='@{/form/items/add}'|" 즉, 사용자가 /form/items/add 로 GET 요청이 보내면 public String addForm(Model model) {...} 호출 addForm() 로직은 1. model.addAttirbute("item", new Item()) : 빈 item 객체를 만들고 모델에 담아 2. addForm.html 에게 전달하는 것이었음 이제, addForm.html 에서 사용자가 입력값을 넣어 /form/items/add 로 POST 요청을 보낸다면 @ModelAttribute Item item 이므로 value(입력값)가 object(item객체)의 각 field(item객체의 필드)들에 바인딩되고 바인딩된 객체는 수정된 객체를 의미하고 이 객체를 item.html로 전달함 (action="item.html") addItem(@ModelAttribute Item item, RedirectAttributes redirectAttributes) {...} 호출될 것 addItem() 로직은 1. save() 1-1. sequence(=PK) 증가시키고 sequence를 item 객체의 id로 설정하고(setter) 1-2. store(=Map)에 id(key)와 item객체(value)를 저장하고 2. redirectAttributes.addAttribute("itemId", savedItem.getId()) : 해당 객체를 리다이렉트 url 의 경로변수로 사용하고 2. redirectAttributes.addAttribute("status", true) : 불린값을 리다이렉트 url 의 쿼리 파라미터로 사용하고 3. "redirect:/form/items/{itemId}" 리다이렉트하는(GET요청) 것이었음 localhost:8080/form/items/{itemId} 으로 GET 요청이 온다면 item(@PathVariable long itemId, Model model) {...} 호출할 것 item() 로직은 1. findById() : {itemId} 를 사용하여 특정 item 객체를 조회하고 2. 그 item 객체를 모델에 담아 item.html 에 전달하는 것이었음 --> <div> <label for="itemName">상품명</label> <input type="text" id="itemName" th:field="*{itemName}" class="form-control" placeholder="이름을 입력하세요"> <!-- th 가 name, value, id 를 만들어준다. *{itemName}: ${item.itemName}의 생략버전. 초기화되지 않은 item 객체이므로 빈 객체. 사용자가 입력값을 넣어 POST 요청을 보내면 폼데이터가 서버로 넘어오고 item 객체에 각 필드들이 바인딩됨 --> </div> <div> <label for="price">가격</label> <input type="text" id="price" th:field="*{price}" class="form-control" placeholder="가격을 입력하세요"> <!-- th 가 name, value, id 를 만들어준다. *{itemName}: ${item.itemName}의 생략버전. 초기화되지 않은 item 객체이므로 빈 객체. 사용자가 입력값을 넣어 POST 요청을 보내면 폼데이터가 서버로 넘어오고 item 객체에 각 필드들이 바인딩됨 --> </div> <div> <label for="quantity">수량</label> <input type="text" id="quantity" th:field="*{quantity}" class="form-control" placeholder="수량을 입력하세요"> <!-- th 가 name, value, id 를 만들어준다. *{itemName}: ${item.itemName}의 생략버전. 초기화되지 않은 item 객체이므로 빈 객체. 사용자가 입력값을 넣어 POST 요청을 보내면 폼데이터가 서버로 넘어오고 item 객체에 각 필드들이 바인딩됨 --> </div> <hr class="my-4"> <!-- single checkbox --> <div>판매 여부</div> <div> <div class="form-check"> <!-- spring 은 히든필드를 운용한다. HTML checkbox 는 체크되지 않으면 서버로 히든필드만 전송한다. 그럼 spring 은 필드가 false 라고 판단한다. HTML 메시지: itemName=22&price=22&quantity=22&_open=on spring: item.open = false HTML checkbox 가 체크되면 필드와 히든필드를 서버로 전송된다. HTML 메시지: itemName=33&price=33&quantity=33&open=on&_open=on. 그럼 spring 은 필드가 true 라고 판단한다. spring: item.open = true --> <input type="checkbox" id="open" th:field="*{open}" class="form-check-input" /> <!-- th 를 사용하면 알아서 히든필드를 만들어내기 때문에 HTML checkbox 를 편하게 사용할 수 있다. --> <label for="open" class="form-check-label">판매 오픈</label> </div> </div> <!-- multi checkbox --> <div> <div>등록 지역</div> <div th:each="region : ${regions}" class="form-check form-check-inline"> <!-- ${regions} : 컨트롤러가 호출될 때 @ModelAttribute regions() 가 호출된 결과로 넘어온 완전체 Map<String, String> region : Map<String, String> 의 요소. String 객체(key값) --> <input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input"> <!-- th 가 name, value, id 을 만들어줌. 이 때, id는 field 에 숫자가 붙여져 고유하게 만들어진다. *{regions} : ${item.regions}의 생략 버전. item 객체은 어떠한 필드도 초기화하지 않는 Item() 생성자로 초기화되어 넘어왔으므로 List<String> regions 필드는 null ${region.key} : 완전체 Map의 key 중 하나. "SEOUL", "BUSAN", "JEJU" 중 하나 (반복문이니깐). 사용자가 서버로 보낼 값 사용자가 0개 이상 3개 이하의 체크박스를 체크해서 POST 요청 보내면 폼데이터가 서버로 넘어오고 item 객체에 각 필드들이 바인딩됨 --> <label th:for="${#ids.prev('regions')}" th:text="${region.value}" class="form-check-label">서울</label> <!-- ${#ids.prev('필드명')} : 바로 이전 필드의 id를 그대로 가져와서 사용. 물론 위 태그에서 th가 id 자동생성해줬다. ${region.value} : 완전체 Map(통짜)의 value 중 하나. "서울", "부산", "제주" 중 하나 (반복문이니깐). label 태그 기본값 대체할 값 --> </div> </div> <!-- radio button --> <div> <div>상품 종류</div> <div th:each="type : ${itemTypes}" class="form-check form-check-inline"> <!-- ${itemTypes} : 컨트롤러가 호출될 때 @ModelAttribute itemTypes() 가 호출된 결과로 넘어온 완전체 ItemType[] (Enum 배열) type : ItemType[] 의 요소. 열거 객체 (반복문이니깐) --> <input type="radio" th:field="*{itemType}" th:value="${type.name()}" class="form-check-input"> <!-- th 가 name, value, id 을 만들어줌. 이 때, id는 field 에 숫자가 붙여져 고유하게 만들어진다. *{itemType} : ${item.itemType}의 생략 버전. item 객체은 어떠한 필드도 초기화하지 않는 Item() 생성자로 초기화되어 넘어왔으므로 ItemType itemType 필드는 null ${type.name()} : 완전체 ItemType[]의 상수 중 하나의 문자열 형태. "BOOK", "FOOD", "ETC" 중 하나 (반복문이니깐). 사용자가 3개 중 1개의 라디오박스를 체크해서 POST 요청 보내면 폼데이터가 서버로 넘어오고 item 객체에 각 필드들이 바인딩됨 --> <label th:for="${#ids.prev('itemType')}" th:text="${type.description}" class="form-check-label"> BOOK</label> <!-- ${#ids.prev('itemType')} : 바로 이전 필드의 id를 그대로 가져와서 사용. 물론 위 태그에서 th가 id 자동생성해줬다. 사용자가 서버로 보낼 값 ${type.description} : 완전체 ItemType[]의 상수 중 하나의 멤버변수(description). "도서", "음식", "기타" 중 하나 (반복문이니깐). label 태그 기본값 대체할 값 --> </div> </div> <!-- SELECT --> <div> <div>배송 방식</div> <select th:field="*{deliveryCode}" class="form-select"> <!-- *{deliveryCode} : ${item.deliveryCode}의 생략 버전. item 객체은 어떠한 필드도 초기화하지 않는 Item() 생성자로 초기화되어 넘어왔으므로 DeliveryCode deliveryCode 필드는 null 사용자가 3개 중 1개의 셀렉트를 체크해서 POST 요청 보내면 폼데이터가 서버로 넘어오고 item 객체에 각 필드들이 바인딩됨 --> <option value="">==배송 방식 선택==</option> <!-- 맨 위에 보여줄 옵션 설정 --> <option th:each="deliveryCode : ${deliveryCodes}" th:value="${deliveryCode.code}" th:text="${deliveryCode.displayName}"> FAST </option> <!-- 그 다음으로 보여줄 옵션들 설정 ${deliveryCodes} : 컨트롤러가 호출될 때 @ModelAttribute deliveryCodes() 가 호출된 결과로 넘어온 완전체 List<DeliveryCode> deliveryCode : List<DeliveryCode> 의 요소. DeliveryCode 객체 (반복문이니깐) ${deliveryCode.code} : Delivery 객체의 멤버변수(String code). "FAST", "NORMAL", "SLOW" 중 하나 (반복문이니깐). 사용자가 서버로 보낼 값 ${deliveryCode.displayName} : Delivery 객체의 멤버변수(String displayName). "빠른배송", "일반배송", "느린배송" 중 하나 (반복문이니깐). option 태그 기본값을 대체할 값 --> </select> </div> <hr class="my-4"> <div class="row"> <div class="col"> <button class="w-100 btn btn-primary btn-lg" type="submit">상품 등록</button> </div> <div class="col"> <button class="w-100 btn btn-secondary btn-lg" onclick="location.href='items.html'" th:onclick="|location.href='@{/form/items}'|" type="button">취소</button> </div> </div> </form> </div> <!-- /container --> </body> </html> editForm.html <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <link th:href="@{/css/bootstrap.min.css}" href="../css/bootstrap.min.css" rel="stylesheet"> <style> .container { max-width: 560px; } </style> </head> <body> <div class="container"> <div class="py-5 text-center"> <h2>상품 수정 폼</h2> </div> <form action="item.html" th:action method="post" th:object="${item}"> <!-- item.html 에서 상품 수정 버튼을 누름 : th:onclick="|location.href='@{/form/items/{itemId}/edit(itemId=${item.id})}'|" 즉, 사용자가 /form/items/{itemId}/edit 로 GET 요청이 보내면 editForm(@PathVariable Long itemId, Model model) {...} 호출 editForm() 로직은 1. findByid() : {itemId} 를 사용하여 특정 item 객체를 조회하고 2. 그 item 객체를 모델에 담아 editForm.html 에 전달하는 것이었음 이제, editForm.html 에서 사용자가 입력값을 넣어 /form/items/{itemId}/edit 로 POST 요청을 보낸다면 @ModelAttribute Item item 이므로 value(입력값)가 object(item객체)의 각 field(item객체의 필드)들에 바인딩되고 바인딩된 객체는 수정된 객체를 의미하고 이 객체를 item.html로 전달함 (action="item.html") editItem(@PathVariable Long itemId, @ModelAttribute Item item) {...} 호출될 것 editItem() 로직은 1. update() 1-1. findById() : {itemId} 를 사용하여 수정할 item 객체를 조회하고 1-2. getter() : 바인딩된 객체(=수정된 객체)의 각 필드들을 조회하고 1-3. setter() : 수정할 item 객체의 각 필드들을 수정된 객체의 각 필드들로 수정하고 2. "redirect:/form/items/{itemId}" 리다이렉트하는(GET요청) 것이었음 localhost:8080/form/items/{itemId} 으로 GET 요청이 온다면 item(@PathVariable long itemId, Model model) {...} 호출할 것 item() 로직은 1. findById() : {itemId} 를 사용하여 특정 item 객체를 조회하고 그 item객체를 모델에 담아 2. item.html 에 전달하는 것이었음 --> <div> <label for="id">상품 ID</label> <input type="text" id="id" class="form-control" th:field="*{id}" readonly> <!-- th 가 name, value, id 를 만들어준다. *{id}: ${item.id}의 생략버전. editForm() 에서 model 에 담겨서 넘어온 특정 Item 객체 (null 아님) 사용자가 입력값을 넣어 POST 요청을 보내면 폼데이터가 서버로 넘어오고 item 객체에 각 필드들이 바인딩됨 --> </div> <div> <label for="itemName">상품명</label> <input type="text" id="itemName" class="form-control" th:field="*{itemName}"> <!-- th 가 name, value, id 를 만들어준다. *{itemName}: ${item.itemName}의 생략버전. editForm() 에서 model 에 담겨서 넘어온 특정 Item 객체 (null 아님) 사용자가 입력값을 넣어 POST 요청을 보내면 폼데이터가 서버로 넘어옴 --> </div> <div> <label for="price">가격</label> <input type="text" id="price" class="form-control" th:field="*{price}"> <!-- th 가 name, value, id 를 만들어준다. *{itemName}: ${item.itemName}의 생략버전. editForm() 에서 model 에 담겨서 넘어온 특정 Item 객체 (null 아님) 사용자가 입력값을 넣어 POST 요청을 보내면 폼데이터가 서버로 넘어옴 --> </div> <div> <label for="quantity">수량</label> <input type="text" id="quantity" class="form-control" th:field="*{quantity}"> <!-- th 가 name, value, id 를 만들어준다. *{quantity}: ${item.quantity}의 생략버전. editForm() 에서 model 에 담겨서 넘어온 특정 Item 객체 (null 아님) 사용자가 입력값을 넣어 POST 요청을 보내면 폼데이터가 서버로 넘어옴 --> </div> <hr class="my-4"> <!-- single checkbox --> <div>판매 여부</div> <div> <div class="form-check"> <!-- spring 은 히든필드를 운용한다. HTML checkbox 는 체크되지 않으면 서버로 히든필드만 전송한다. 그럼 spring 은 필드가 false 라고 판단한다. HTML 메시지: itemName=22&price=22&quantity=22&_open=on spring: item.open = false HTML checkbox 가 체크되면 필드와 히든필드를 서버로 전송된다. HTML 메시지: itemName=33&price=33&quantity=33&open=on&_open=on. 그럼 spring 은 필드가 true 라고 판단한다. spring: item.open = true --> <input type="checkbox" id="open" th:field="*{open}" class="form-check-input"> <!-- th 가 name, value, id 를 만들어준다. *{open} : ${item.open}의 생략 버전. editForm() 에서 model 에 담겨져 넘어온 특정 item 객체의 open(Boolean객체) 사용자가 입력값을 넣어 POST 요청을 보내면 폼데이터가 서버로 넘어옴 --> <label for="open" class="form-check-label">판매 오픈</label> </div> </div> <!-- multi checkbox --> <div> <div>등록 지역</div> <div th:each="region : ${regions}" class="form-check form-check-inline"> <!-- ${regions} : 컨트롤러가 호출될 때 @ModelAttribute regions() 가 호출된 결과로 넘어온 완전체 Map<String, String> region : Map<String, String> 의 요소. String 객체(key값) --> <input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input"> <!-- th 가 name, value, id 을 만들어줌. 이 때, id는 field 에 숫자가 붙여져 고유하게 만들어진다. *{regions} : ${item.regions}의 생략 버전. item 객체은 어떠한 필드도 초기화하지 않는 Item() 생성자로 초기화되어 넘어왔으므로 List<String> regions 필드는 null ${region.key} : 완전체 Map의 key 중 하나. "SEOUL", "BUSAN", "JEJU" 중 하나 (반복문이니깐). 사용자가 서버로 보낼 값 사용자가 0개 이상 3개 이하의 체크박스를 체크해서 POST 요청 보내면 폼데이터가 서버로 넘어옴 --> <label th:for="${#ids.prev('regions')}" th:text="${region.value}" class="form-check-label">서울</label> <!-- ${#ids.prev('필드명')} : 바로 이전 필드의 id를 그대로 가져와서 사용. 물론 위 태그에서 th가 id 자동생성해줬다. ${region.value} : 완전체 Map(통짜)의 value 중 하나. "서울", "부산", "제주" 중 하나 (반복문이니깐). label 태그 기본값 대체할 값 --> </div> </div> <!-- radio button --> <div> <div>상품 종류</div> <div th:each="type : ${itemTypes}" class="form-check form-check-inline"> <!-- ${itemTypes} : 컨트롤러가 호출될 때 @ModelAttribute itemTypes() 가 호출된 결과로 넘어온 완전체 ItemType[] (Enum 배열) type : ItemType[] 의 요소. 열거 객체 (반복문이니깐) --> <input type="radio" th:field="*{itemType}" th:value="${type.name()}" class="form-check-input"> <!-- th 가 name, value, id 을 만들어줌. 이 때, id는 field 에 숫자가 붙여져 고유하게 만들어진다. *{itemType} : ${item.itemType}의 생략 버전. item 객체은 어떠한 필드도 초기화하지 않는 Item() 생성자로 초기화되어 넘어왔으므로 ItemType itemType 필드는 null ${type.name()} : 완전체 ItemType[]의 상수 중 하나의 문자열 형태. "BOOK", "FOOD", "ETC" 중 하나 (반복문이니깐). 사용자가 3개 중 1개의 라디오박스를 체크해서 POST 요청 보내면 폼데이터가 서버로 넘어옴 --> <label th:for="${#ids.prev('itemType')}" th:text="${type.description}" class="form-check-label"> BOOK</label> <!-- ${#ids.prev('itemType')} : 바로 이전 필드의 id를 그대로 가져와서 사용. 물론 위 태그에서 th가 id 자동생성해줬다. 사용자가 서버로 보낼 값 ${type.description} : 완전체 ItemType[]의 상수 중 하나의 멤버변수(description). "도서", "음식", "기타" 중 하나 (반복문이니깐). label 태그 기본값 대체할 값 --> </div> </div> <!-- SELECT --> <div> <div>배송 방식</div> <select th:field="*{deliveryCode}" class="form-select"> <!-- *{deliveryCode} : ${item.deliveryCode}의 생략 버전. item 객체은 어떠한 필드도 초기화하지 않는 Item() 생성자로 초기화되어 넘어왔으므로 DeliveryCode deliveryCode 필드는 null 사용자가 3개 중 1개의 셀렉트를 체크해서 POST 요청 보내면 폼데이터가 서버로 넘어옴 --> <option value="">==배송 방식 선택==</option> <!-- 맨 위에 보여줄 옵션 설정 --> <option th:each="deliveryCode : ${deliveryCodes}" th:value="${deliveryCode.code}" th:text="${deliveryCode.displayName}"> FAST </option> <!-- 그 다음으로 보여줄 옵션들 설정 ${deliveryCodes} : 컨트롤러가 호출될 때 @ModelAttribute deliveryCodes() 가 호출된 결과로 넘어온 완전체 List<DeliveryCode> deliveryCode : List<DeliveryCode> 의 요소. DeliveryCode 객체 (반복문이니깐) ${deliveryCode.code} : Delivery 객체의 멤버변수(String code). "FAST", "NORMAL", "SLOW" 중 하나 (반복문이니깐). 사용자가 서버로 보낼 값 ${deliveryCode.displayName} : Delivery 객체의 멤버변수(String displayName). "빠른배송", "일반배송", "느린배송" 중 하나 (반복문이니깐). option 태그 기본값을 대체할 값 --> </select> </div> <div class="row"> <div class="col"> <button class="w-100 btn btn-primary btn-lg" type="submit">저장</button> </div> <div class="col"> <button class="w-100 btn btn-secondary btn-lg" onclick="location.href='item.html'" th:onclick="|location.href='@{/form/items/{itemId}(itemId=${item.id})}'|" type="button">취소</button> </div> </div> </form> </div> <!-- /container --> </body> </html> item.html <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <link th:href="@{/css/bootstrap.min.css}" href="../css/bootstrap.min.css" rel="stylesheet"> <style> .container { max-width: 560px; } </style> </head> <body> <!-- ${param.status} : addItem() 또는 editItem() 에서 "redirect:/form/items/{itemId}" 로 리다이렉트해왔음 "redirect:/form/items/{itemId}" url 로 요청이 들어왔기 때문에 item() 로직 수행됨 item() 로직에서 경로변수 인자를 사용하여 특정 item 객체를 조회하고 item 객체를 model에 담고 item.html 로 보냄 --> <div class="container"> <div class="py-5 text-center"> <h2>상품 상세</h2> </div> <!-- 추가 --> <h2 th:if="${param.status}" th:text="'저장 완료'"></h2> <!-- ${param.status} : addItem()에서 "redirect:/form/items/{itemId}" 로 리다이렉트해왔음 즉, http://localhost:8080/form/items/3?status=true 이런 식으로 리다이렉트 (addItem()에서 redirectAttributes 로 itemId, status 를 설정했음. itemId, status는 한번 설정하면 불변해야 하므로 editItem()에선 rdirectAttributes 설정하지 않음) itemId 는 이미 리다이렉트 url로 사용되었고 status 는 param 으로 url 경로변수에 접근하여 속성을 추출하여 사용하면 된다. --> <div> <label for="itemId">상품 ID</label> <input type="text" id="itemId" name="itemId" class="form-control" value="1" th:value="${item.id}" readonly> <!-- th 가 name, value, id 를 만들어준다. ${item.id} : 사용자가 addForm.html 또는 editForm.html 에서 입력값을 넣어 POST 요청을 보내면 value가 서버로 넘어갔었다. 서버는 쿼리 문자열을 받아(getter) Item 객체의 각 필드에 매핑(setter)했었다. 그 Item 객체가 FormItemController 의 addItem() 또는 editItem()에 의해 item.html 로 리다이렉트되었다. 그 Item 객체를 item 라는 이름으로 다시 각각 add() 또는 editItem()이 호출되어 리다이렉트할 때 넘겨준 Item 객체 사용자가 입력값을 넣어 POST 요청을 보내면 value가 서버로 넘어가고, 서버는 쿼리 문자열을 받아(getter) Item 객체의 각 필드(Long id)에 매핑한다(setter) 이후 form 태그의 action 과 method 에 따라 행동하면 된다 --> </div> <div> <label for="itemName">상품명</label> <input type="text" id="itemName" name="itemName" class="form-control" value="상품A" th:value="${item.itemName}" readonly> <!-- *{itemName}: ${item.itemName}의 생략버전. 초기화되지 않은 item 객체이므로 빈 객체. 사용자가 입력값을 넣어 POST 요청을 보내면 서버는 쿼리 문자열을 받아(getter) Item 객체의 각 필드(String itemName)에 매핑한다(setter) 이후 form 태그의 action 과 method 에 따라 행동하면 된다 <input type="text" id="itemName" name="itemName" th:field="*{itemName}" class="form-control" placeholder="이름을 입력하세요"> --> </div> <div> <label for="price">가격</label> <input type="text" id="price" name="price" class="form-control" value="10000" th:value="${item.price}" readonly> </div> <div> <label for="quantity">수량</label> <input type="text" id="quantity" name="quantity" class="form-control" value="10" th:value="${item.quantity}" readonly> </div> <hr class="my-4"> <!-- single checkbox --> <div>판매 여부</div> <div> <div class="form-check"> <input type="checkbox" id="open" th:field="${item.open}" class="form-check-input" disabled> <!-- th 가 name, value, id 을 만들어줌 체크박스가 체크되어 있다면 checked="checked" 속성까지 만들어줌. 체크되지 않았다면 속성 만들어지지 않음. --> <label for="open" class="form-check-label">판매 오픈</label> </div> </div> <!-- multi checkbox --> <div> <div>등록 지역</div> <div th:each="region : ${regions}" class="form-check form-check-inline"> <!-- @ModelAttribute 에 담았던 것 반복문 돌리기 --> <!-- @ModelAttribute 에 담겨서 넘어온 것(regions()) 반복문 돌리기 ${regions} : Map<String, String>. 사용자가 선택해서 넘어온 것이 아니라 FormItemController 에서 @ModelAttribute 자체가 그대로 넘어왔기 때문. --> <input type="checkbox" th:field="${item.regions}" th:value="${region.key}" class="form-check-input" disabled> <!-- th 가 name, value, id 을 만들어줌. 이 때, id는 field 에 숫자가 붙여져 고유하게 만들어진다. ${item.regions} : List. 사용자가 선택했던 요소들이 담긴 리스트이므로 ["SEOUL", "BUSAN"] 등의 리스트. ${region.key} : 위 div 태그의 Map의 key 하나. "SEOUL", "BUSAN", "JEJU" 중 하나 (반복문이니깐) value("SEOUL", "BUSAN", "JEJU" 중 하나)가 field(Map<String, String>) 의 요소에 존재한다면 th가 checked="checked" 속성을 만들어줌. --> <label th:for="${#ids.prev('regions')}" th:text="${region.value}" class="form-check-label">서울</label> <!-- ${#ids.prev('필드명')} : 바로 이전 input 태그에서 사용되었던 id를 그대로 가져와서 사용. 물론 위 태그에서 th가 id 자동생성해줬다. ${region.value} : 위 div 태그의 Map의 value 하나. "서울", "부산", "제주" 중 하나 (반복문이니깐) --> </div> </div> <!-- radio button --> <div> <div>상품 종류</div> <div th:each="type : ${itemTypes}" class="form-check form-check-inline"> <!-- @ModelAttribute 에 담겨서 넘어온 것(itemTypes()) 반복문 돌리기 ${itemTypes} : ItemType[](ENUM배열). 사용자가 선택해서 넘어온 것이 아니라 FormItemController 에서 @ModelAttribute 자체가 그대로 넘어왔기 때문. --> <input type="radio" th:field="${item.itemType}" th:value="${type.name()}" class="form-check-input" disabled> <!-- th 가 name, value, id 을 만들어줌. 이 때, id는 field 에 숫자가 붙여져 고유하게 만들어진다. ${item.itemType} : ENUM. 사용자가 선택했던 ENUM. ${type.name()} : 위 div 태그의 ENUM배열의 ENUM 중 하나의 문자열 형태. "BOOK", "FOOD", "ETC" 중 하나 (반복문이니깐). 사용자가 각 라디오박스를 체크해서 POST 요청 보낼 때 item.itemType 에 문자열이 바인딩되어 날아감. 이후 서버에서 다시 상수로 변환하여 itemType에 저장함. value("BOOK", "FOOD", "ETC" 중 하나)가 field(사용자가 선택했던 ENUM)와 일치한다면 th가 checked="checked" 속성을 만들어줌. --> <label th:for="${#ids.prev('itemType')}" th:text="${type.description}" class="form-check-label"> BOOK</label> <!-- ${#ids.prev('필드명')} : 바로 이전 태그에서 사용되었던 id를 그대로 가져와서 사용. 물론 위 태그에서 th가 id 자동생성해줬다. ${type.description} : 위 div 태그의 ENUM배열의 ENUM 중 하나의 값. "도서", "음식", "기타" 중 하나 (반복문이니깐). --> </div> </div> <div class="row"> <div class="col"> <button class="w-100 btn btn-primary btn-lg" onclick="location.href='editForm.html'" th:onclick="|location.href='@{/form/items/{itemId}/edit(itemId=${item.id})}'|" type="button">상품 수정</button> </div> <div class="col"> <button class="w-100 btn btn-secondary btn-lg" onclick="location.href='items.html'" th:onclick="|location.href='@{/form/items}'|" type="button">목록으로</button> </div> </div> </div> <!-- /container --> </body> </html>
미해결
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? ( 예 /아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? ( 예 /아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? ( 예 /아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 안녕하세요. 강의 내에서 스프링 없이 테스트 코드를 짜는 것이 좋다고 하신 것을 보고 실제로 테스트 코드는 스프링을 의존하지 않고 짜는 것이 무엇인지 궁금해졌습니다. 실제로 강의에서 작성하는 내용 중에, 어느 부분이 스프링에 의존해서 테스트를 한 것인지, 또한 그러한 스프링 의존 테스트를 순수 자바 기반의 테스트로 바꾸며 어떤 식으로 나오게 될지 궁금합니다. 감사합니다.
미해결
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
제가 공부하면서 주석으로 정리한 것 있는데 하찮은 실력이지만 다른 공부하시는 분들께 도움이 될 수 있을까 해서 공부한 내용을 올려봅니다! 범위는 "체크박스-멀티"까지 내용입니다! addForm.html <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <link th:href="@{/css/bootstrap.min.css}" href="../css/bootstrap.min.css" rel="stylesheet"> <style> .container { max-width: 560px; } </style> </head> <body> <div class="container"> <div class="py-5 text-center"> <h2>상품 등록 폼</h2> </div> <form action="item.html" th:action method="post" th:object="${item}"> <!-- ${item} : addForm() 에서 model 에 담겨서 넘어온 새로운 객체 (아래 코드 주석) model.addAttribute("item", new Item()); --> <div> <label for="itemName">상품명</label> <input type="text" id="itemName" th:field="*{itemName}" class="form-control" placeholder="이름을 입력하세요"> <!-- <input type="text" id="itemName" name="itemName" th:field="*{itemName}" class="form-control" placeholder="이름을 입력하세요"> --> </div> <div> <label for="price">가격</label> <input type="text" id="price" th:field="*{price}" class="form-control" placeholder="가격을 입력하세요"> <!-- <input type="text" id="price" name="price" class="form-control" placeholder="가격을 입력하세요"> --> </div> <div> <label for="quantity">수량</label> <input type="text" id="quantity" th:field="*{quantity}" class="form-control" placeholder="수량을 입력하세요"> <!-- <input type="text" id="quantity" name="quantity" class="form-control" placeholder="수량을 입력하세요"> --> </div> <hr class="my-4"> <!-- single checkbox --> <div>판매 여부</div> <div> <div class="form-check"> <!-- 히든필드 추가 <input type="checkbox" id="open" name="open" class="form-check-input" /> <input type="hidden" id="_open" name="_open" value="on" /> --> <!-- HTML checkbox 는 체크하지 않으면 서버로 값 자체를 보내지 않는다. (히든필드 사용하지 않을 경우) HTML 메시지: itemName=11&price=11&quantity=11 spring: item.open = null 즉. HTML checkbox 는 사용하기 불편할 수 있다. 그래서 spring 은 히든필드를 운용한다. HTML checkbox 는 체크되지 않으면 서버로 히든필드만 전송한다. 그럼 spring 은 필드가 false 라고 판단한다. HTML 메시지: itemName=22&price=22&quantity=22&_open=on spring: item.open = false HTML checkbox 가 체크되면 필드와 히든필드를 서버로 전송된다. HTML 메시지: itemName=33&price=33&quantity=33&open=on&_open=on. 그럼 spring 은 필드가 true 라고 판단한다. spring: item.open = true --> <input type="checkbox" id="open" th:field="*{open}" class="form-check-input" /> <!-- th 를 사용하면 알아서 히든필드를 만들어내기 때문에 HTML checkbox 를 편하게 사용할 수 있다. --> <label for="open" class="form-check-label">판매 오픈</label> </div> </div> <!-- multi checkbox --> <div> <div>등록 지역</div> <div th:each="region : ${regions}" class="form-check form-check-inline"> <!-- @ModelAttribute 에 담겨서 넘어온 것(regions()) 반복문 돌리기 ${regions} : Map<String, String>. 사용자가 선택해서 넘어온 것이 아니라 FormItemController 에서 @ModelAttribute 자체가 그대로 넘어왔기 때문. --> <input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input"> <!-- th 가 name, value, id 을 만들어줌. 이 때, id는 field 에 숫자가 붙여져 고유하게 만들어진다. *{regions} : ${item.regions}의 생략 버전. Map<String, String>. 사용자가 선택해서 넘어온 것이 아니라 FormItemController 에서 @ModelAttribute 자체가 그대로 넘어왔기 때문. ${region.key} : 위 div 태그의 Map의 key 중 하나. "SEOUL", "BUSAN", "JEJU" 중 하나 (반복문이니깐). 사용자가 각 체크박스를 체크해서 POST 요청 보낼 때 regions.key가 날아감. 이후 item.regions 에 값이 바인딩될 것. --> <label th:for="${#ids.prev('regions')}" th:text="${region.value}" class="form-check-label">서울</label> <!-- ${#ids.prev('필드명')} : 바로 이전 태그에서 사용되었던 id를 그대로 가져와서 사용. 물론 위 태그에서 th가 id 자동생성해줬다. ${region.value} : 위 div 태그의 Map의 value 중 하나. "서울", "부산", "제주" 중 하나 (반복문이니깐) --> </div> </div> <div> <div>상품 종류</div> <div th:each="type : ${itemTypes}" class="form-check form-check-inline"> <!-- @ModelAttribute 에 담겨서 넘어온 것(itemTypes()) 반복문 돌리기 ${regions} : ItemTypes[]. 사용자가 선택해서 넘어온 것이 아니라 FormItemController 에서 @ModelAttribute 자체가 그대로 넘어왔기 때문. --> <input type="radio" th:field="*{itemType}" th:value="${type.name()}" class="form-check-input"> <!-- *{itemType} : --> <label th:for="${#ids.prev('itemType')}" th:text="${type.description}" class="form-check-label"> BOOK </label> <!-- --> </div> </div> <div class="row"> <div class="col"> <button class="w-100 btn btn-primary btn-lg" type="submit">상품 등록</button> </div> <div class="col"> <button class="w-100 btn btn-secondary btn-lg" onclick="location.href='items.html'" th:onclick="|location.href='@{/form/items}'|" type="button">취소</button> </div> </div> </form> </div> <!-- /container --> </body> </html> editForm.html <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <link th:href="@{/css/bootstrap.min.css}" href="../css/bootstrap.min.css" rel="stylesheet"> <style> .container { max-width: 560px; } </style> </head> <body> <div class="container"> <div class="py-5 text-center"> <h2>상품 수정 폼</h2> </div> <form action="item.html" th:action method="post" th:object="${item}"> <!-- ${item} : editForm() 에서 model 에 담겨서 넘어온 특정 객체 (아래 코드 주석) Item item = itemRepository.findById(itemId); model.addAttribute("item", item); --> <div> <label for="id">상품 ID</label> <input type="text" id="id" class="form-control" th:field="*{id}" readonly> <!-- th 가 name, value, id 를 만들어준다. <input type="text" id="id" name="id" class="form-control" value="1" th:value="${item.id}" readonly> --> </div> <div> <label for="itemName">상품명</label> <input type="text" id="itemName" class="form-control" th:field="*{itemName}"> <!-- th 가 name, value, id 를 만들어준다. <input type="text" id="itemName" name="itemName" class="form-control" value="상품A" th:value="${item.itemName}"> --> </div> <div> <label for="price">가격</label> <input type="text" id="price" class="form-control" th:field="*{price}"> <!-- th 가 name, value, id 를 만들어준다. <input type="text" id="price" name="price" class="form-control" value="10000" th:value="${item.price}"> --> </div> <div> <label for="quantity">수량</label> <input type="text" id="quantity" class="form-control" th:field="*{quantity}"> <!-- th 가 name, value, id 를 만들어준다. <input type="text" id="quantity" name="quantity" class="form-control" value="10" th:value="${item.quantity}"> --> </div> <hr class="my-4"> <!-- single checkbox --> <div>판매 여부</div> <div> <div class="form-check"> <input type="checkbox" id="open" th:field="*{open}" class="form-check-input"> <label for="open" class="form-check-label">판매 오픈</label> </div> </div> <!-- multi checkbox --> <div> <div>등록 지역</div> <div th:each="region : ${regions}" class="form-check form-check-inline"> <!-- @ModelAttribute 에 담겨서 넘어온 것(regions()) 반복문 돌리기 ${regions} : Map<String, String>. 사용자가 선택해서 넘어온 것이 아니라 FormItemController 에서 @ModelAttribute 자체가 그대로 넘어왔기 때문. --> <input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input"> <!-- th 가 name, value, id 을 만들어줌. 이 때, id는 field 에 숫자가 붙여져 고유하게 만들어진다. *{regions} : ${item.regions}의 생략 버전. 빈 리스트. 사용자가 각 체크박스를 체크해서 POST 요청 보낼 때 regions.key가 날아감. item.regions 에 값이 바인딩될 것. ${region.key} : 위 div 태그의 Map의 key 중 하나. "SEOUL", "BUSAN", "JEJU" 중 하나 (반복문이니깐). 사용자가 각 체크박스를 체크해서 POST 요청 보낼 때 regions.key가 날아감. 이후 item.regions 에 값이 바인딩될 것. --> <label th:for="${#ids.prev('regions')}" th:text="${region.value}" class="form-check-label">서울</label> <!-- ${#ids.prev('필드명')} : 바로 이전 태그에서 사용되었던 id를 그대로 가져와서 사용. 물론 위 태그에서 th가 id 자동생성해줬다. ${region.value} : 위 div 태그의 Map의 value 하나. "서울", "부산", "제주" 중 하나 (반복문이니깐) --> </div> </div> <div class="row"> <div class="col"> <button class="w-100 btn btn-primary btn-lg" type="submit">저장</button> </div> <div class="col"> <button class="w-100 btn btn-secondary btn-lg" onclick="location.href='item.html'" th:onclick="|location.href='@{/form/items/{itemId}(itemId=${item.id})}'|" type="button">취소</button> </div> </div> </form> </div> <!-- /container --> </body> </html> item.html <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <link th:href="@{/css/bootstrap.min.css}" href="../css/bootstrap.min.css" rel="stylesheet"> <style> .container { max-width: 560px; } </style> </head> <body> <div class="container"> <div class="py-5 text-center"> <h2>상품 상세</h2> </div> <!-- 추가 --> <h2 th:if="${param.status}" th:text="'저장 완료'"></h2> <div> <label for="itemId">상품 ID</label> <input type="text" id="itemId" name="itemId" class="form-control" value="1" th:value="${item.id}" readonly> </div> <div> <label for="itemName">상품명</label> <input type="text" id="itemName" name="itemName" class="form-control" value="상품A" th:value="${item.itemName}" readonly> </div> <div> <label for="price">가격</label> <input type="text" id="price" name="price" class="form-control" value="10000" th:value="${item.price}" readonly> </div> <div> <label for="quantity">수량</label> <input type="text" id="quantity" name="quantity" class="form-control" value="10" th:value="${item.quantity}" readonly> </div> <hr class="my-4"> <!-- single checkbox --> <div>판매 여부</div> <div> <div class="form-check"> <input type="checkbox" id="open" th:field="${item.open}" class="form-check-input" disabled> <!-- th 가 name, value, id 을 만들어줌 체크박스가 체크되어 있다면 checked="checked" 속성까지 만들어줌. 체크되지 않았다면 속성 만들어지지 않음. --> <label for="open" class="form-check-label">판매 오픈</label> </div> </div> <!-- multi checkbox --> <div> <div>등록 지역</div> <div th:each="region : ${regions}" class="form-check form-check-inline"> <!-- @ModelAttribute 에 담았던 것 반복문 돌리기 --> <!-- @ModelAttribute 에 담겨서 넘어온 것(regions()) 반복문 돌리기 ${regions} : Map<String, String>. 사용자가 선택해서 넘어온 것이 아니라 FormItemController 에서 @ModelAttribute 자체가 그대로 넘어왔기 때문. --> <input type="checkbox" th:field="${item.regions}" th:value="${region.key}" class="form-check-input" disabled> <!-- th 가 name, value, id 을 만들어줌. 이 때, id는 field 에 숫자가 붙여져 고유하게 만들어진다. ${item.regions} : List. 사용자가 선택했던 요소들이 담긴 리스트이므로 ["SEOUL", "BUSAN"] 등의 리스트. ${region.key} : 위 div 태그의 Map의 key 하나. "SEOUL", "BUSAN", "JEJU" 중 하나 (반복문이니깐) value("SEOUL", "BUSAN", "JEJU" 중 하나)가 field(Map<String, String>) 의 요소에 존재한다면 th가 checked="checked" 속성을 만들어줌. --> <label th:for="${#ids.prev('regions')}" th:text="${region.value}" class="form-check-label">서울</label> <!-- ${#ids.prev('필드명')} : 바로 이전 input 태그에서 사용되었던 id를 그대로 가져와서 사용. 물론 위 태그에서 th가 id 자동생성해줬다. ${region.value} : 위 div 태그의 Map의 value 하나. "서울", "부산", "제주" 중 하나 (반복문이니깐) --> </div> </div> <div class="row"> <div class="col"> <button class="w-100 btn btn-primary btn-lg" onclick="location.href='editForm.html'" th:onclick="|location.href='@{/form/items/{itemId}/edit(itemId=${item.id})}'|" type="button">상품 수정</button> </div> <div class="col"> <button class="w-100 btn btn-secondary btn-lg" onclick="location.href='items.html'" th:onclick="|location.href='@{/form/items}'|" type="button">목록으로</button> </div> </div> </div> <!-- /container --> </body> </html>
미해결
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 검증1 - validation 강의에서 validator 분리2 섹션에서 설명하실때 파라미터 바인딩한다고 하셨는데 파라미터 바인딩이란게 정확히 뭔가요?? 넘어오는 파라미터를 매개변수로 매핑하는 건가요??
미해결
스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
# hello-template.html <!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <body> <p th:text="'hello '+ ${name}">hello. empty</p> </body> </html> package sebdev.prac1.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class HelloController { @GetMapping("hello") public String hello(Model model){ model.addAttribute("data","spring"); return "hello"; } @GetMapping("hello-mvc") public String helloMvc(@RequestParam("name") String name, Model model){ model.addAttribute("name", name); return "hello-template"; } } 리턴값 hello-template에 맞춰 hello-template.html으로 맞춰주었는데 이런식으로 오류가 납니다.