@Slf4j @Controller public class ExampleExceptionControllerAdvice { //사용자가 Argument를 잘못 보낸 경우 @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(IllegalArgumentException.class) public ErrorResult illegalExHandle(IllegalArgumentException e){ log.error("[exceptionHandle] ex",e); if(1==1) { //throw new RuntimeException("예외 발생"); } return new ErrorResult("BAD", e.getMessage()); } @ResponseBody @GetMapping("/api/members") public String members(){ if(1==1){ throw new IllegalArgumentException("예외"); } return "Hello"; } } members 메서드에서 오류를 강제로 발생시킨 후, illegalExHandle 메서드에서 오류를 catch한 뒤 응답을 하는 것으로 강의 내용을 이해하였습니다. 이럴 경우, 트랜잭션 롤백이 발생하기 위해서는 어떻게 해야 하는 지 알고 싶습니다. [첨부 - 챗 GPT 답변] 예시 코드 @Service public class MyService { @Transactional public void doSomething() { // Some business logic throw new RuntimeException("Something went wrong"); } } @Controller public class MyController { @Autowired private MyService myService; @PostMapping("/example") public String handleRequest() { myService.doSomething(); return "success"; } @ExceptionHandler(RuntimeException.class) public String handleRuntimeException(RuntimeException ex) { // Exception handling logic // If we return without re-throwing the exception return "error"; } } 위의 예제에서 doSomething() 메서드에서 발생한 RuntimeException 이 handleRuntimeException 메서드에서 처리되면, 예외가 다시 던져지지 않으므로 트랜잭션은 롤백되지 않습니다. 결론 @Transactional 이 서비스 계층에 있고, @ExceptionHandler 가 컨트롤러 계층에 있을 때, 예외를 @ExceptionHandler 에서 잡아 처리한 후 다시 던지지 않으면 트랜잭션은 롤백되지 않습니다. 만약 트랜잭션이 롤백되길 원한다면, @ExceptionHandler 에서 예외를 다시 던져야 합니다.
4강 레퍼클래스 로또 번호 생성기 질문 있습니다. package class04wrapperClass; import java.util.Random; public class Lottery { public static void main(String args[]) { //랜덤 생성자 선언 ==> 로또 값이 그때 그때 바뀜 Random random = new Random(); //로또 범위 지정 배열 int[] randomArray = new int[6]; //로또 배열에 로또 값 넣기 for (int i = 0; i < randomArray.length; i++) { int randomValue=random.nextInt(45)+1; randomArray[i]=randomValue; if (randomArray[i]==randomArray[i++]||randomArray[i]==0) randomArray[i]=random.nextInt(45)+1; } for(int i =0; i<randomArray.length; i++){ System.out.print(randomArray[i]+" , "); } } } 이렇게 풀었는데 이것도 올바른 풀이 일까요???
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 새로고침 시 상품이 중복 등록되는 문제는 POST가 멱등하기 때문인 것이 맞나요? /add에서 @ModelAttribute로 Item 객체를 바로 만들어서 save했는데, 이 경우 Dto를 거쳐서 저장하는 것이 올바른 방법인가요? @Data public class ItemDto { private String itemName; private Integer price; private Integer quantity; } @PostMapping("/add") public String addItemTest(@ModelAttribute ItemDto itemDto) { Item item = new Item(itemDto.getItemName(), itemDto.getPrice(), itemDto.getQuantity()); itemRepository.save(item); return "basic/item"; } dto를 사용하는 방식으로 변경해봤는데, id가 null이라는 예외가 발생했습니다. org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'id' cannot be found on null 에러페이지가 나오지만 목록 페이지로 갔을 때 상품은 정상적으로 저장이 되고 있습니다. controller의 save부분에서 item의 id가 자동으로 생성되고 있는데, 왜 이런 문제가 발생하는지 궁금합니다. -- 수정 -- @PostMapping("/add") public String addItemTest(@ModelAttribute ItemDto itemDto) { Item item = new Item(itemDto.getItemName(), itemDto.getPrice(), itemDto.getQuantity()); itemRepository.save(item); return "redirect:/basic/items/" + item.getId(); } redirect로 수정하니 3번 문제는 해결되었습니다. 하지만 이전 코드에서 왜 저런 예외가 떴는지는 아직 모르겠습니다.
import React, { useState, MouseEvent } from "react"; import * as S from "./mypoint.index.styles"; import TapPointLoading from "./mypoint_loading"; import TapPointBuying from "./mypoint_buying"; import TapPointAll from "./mypoint_all"; import TapPointSelling from "./mypoint_selling"; export default function MyPoint(): JSX.Element { const [selectedValue, setSelectedValue] = useState<{ name: string; index: number; }>({ name: "전체내역", index: 0, }); const MyPageHeadInfoButton = [ { name: "전체내역", component: <TapPointAll /> }, { name: "충전내역", component: <TapPointLoading /> }, { name: "구매내역", component: <TapPointBuying /> }, { name: "판매내역", component: <TapPointSelling /> }, ]; const onClickTap = ( event: MouseEvent<HTMLDivElement>, index: number ): void => { const newValue = event.currentTarget.id; setSelectedValue({ name: newValue, index, }); }; // 버튼 클릭으로 해당 data 값을 보여주기 위함 const renderData = (): JSX.Element | undefined => { return ( <S.TableWrap> {/* 해당 탭의 배열의 객체 name통해 컴포넌트 가져옴 */} {MyPageHeadInfoButton.map((el) => { if (el.name === selectedValue.name && el.component) { return <div key={el.name}>{el.component}</div>; } return null; })} </S.TableWrap> ); }; return ( <S.Wrap> <S.MyPageHeadWrap> <S.MyPageHeadBtn> {/* 서브 탭 버튼 */} {MyPageHeadInfoButton.map((el, index) => ( <S.MyPageInfoBtn key={el.name} id={el.name} onClick={(event) => onClickTap(event, index)} selected={selectedValue.name === el.name} > {el.name} </S.MyPageInfoBtn> ))} </S.MyPageHeadBtn> </S.MyPageHeadWrap> <S.MyPageBodyWrap> {/* 해당 탭 data */} <div>{renderData()}</div> </S.MyPageBodyWrap> </S.Wrap> ); } 이렇게 탭을 클릭을 해서 해당 컴포넌트가 보이도록 했습니다. 그러면서 각각의 API data도 받아와 cache에 저장을 하도록 해 추가 API 요청이 일어나지 않도록 했는데 여기서 로그아웃을 하고 다른 아이디로 로그인을 하면 이전의 로그인 했던 data가 그대로 남아있어 최신 data를 가져오기 위해 여러가지 방법으로 시도했습니다. 로그아웃 시 useApolloClient를 활용해 cache를 삭제 했습니다. 이렇게 하면 다시 로그인 한 유저의 data를 잘 가져오는데 로그아웃을 하면서 cache data가 삭제되니 다른 API, Board, Markets 등 해당 page의 사용한 query문의 data를 다시 요청하는 문제가 있습니다. refetch()로 query문을 선언하면 해당 refetch()를 실행하지 않아도 API 요청이 일어나 refetchQueries를 사용해 data 최신화 하려는데 그렇게 되면 모든 탭을 refetch 해줘야 되는 문제가 있습니다. 각 탭 이동마다 API 요청 나가는게 싫어서 fetchporicy나 refetch()를 사용 하지 않았는데 보통 어떻게 사용을 하나요? 로그인에 의한 data는 탭 이동마다 refetch를 시켜주는게 좋을까요? 그리고 구매, 충전 등 하면 바로 MyPoint에 업데이트 되도록 client.writeQuery / readQeury 나 refetchQueries를 사용했는데 이런 결제 정보 같은거는 refetch로 실시간으로 data를 가져오는게 좋겠죠? 로그인, 로그아웃은 LayoutHeader에서 사용하고 있습니다.
안녕하세요. 이전 7강의 메모리 구조와 헷갈리는 부분이 있어서 질문드립니다. 7강의 자바 메모리 구조에서는 다음과 같이 메서드는 공통됐기 때문에 메서드 영역에서 관리한다고 이해했습니다. 그러나 상속 부분에서는 힙영역에서 메서드를 관리하고 사용하는 것처럼 되어있어서 헷갈립니다. 설명을 편리하게 하고자 이렇게 설명하신 걸까요?? 잘못 이해한 부분이 어딘지 모르겠습니다 ㅠㅠ 감사합니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] jpql 구문이 실행될 때 flush가 자동으로 호출 된다고 하셨는데 당연히 flush로 쓰기 지연 SQL 저장소에 있는 쿼리들을 데이터베이스에 반영하고 commit 한 후 jpql 구문이 실행되는거겠죠?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] @Slf4j @SpringBootTest class MemberServiceV3_3Test { @Autowired private MemberRepositoryV3 memberRepository; @Autowired private MemberServiceV3_3 memberService; @BeforeEach void before() { DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD); memberRepository = new MemberRepositoryV3(dataSource); PlatformTransactionManager transactionManager = new DataSourceTransactionManager(dataSource); memberService = new MemberServiceV3_3(memberRepository); } @AfterEach void after() throws SQLException { memberRepository.delete("memberA"); memberRepository.delete("memberB"); memberRepository.delete("ex"); } @Test @DisplayName("정상 이체") void accountTransfer() throws SQLException { //given Member memberA = new Member("memberA", 10000); Member memberB = new Member("memberB", 10000); memberRepository.save(memberA); memberRepository.save(memberB); //when memberService.accountTransfer(memberA.getMemberId(), memberB.getMemberId(), 2000); //then Member findMemberA = memberRepository.findById(memberA.getMemberId()); Member findMemberB = memberRepository.findById(memberB.getMemberId()); assertThat(findMemberA.getMoney()).isEqualTo(8000); assertThat(findMemberB.getMoney()).isEqualTo(12000); } @Test @DisplayName("이체중 예외 발생") void accountTransferEx() throws SQLException { //given Member memberA = new Member("memberA", 10000); Member memberEx = new Member("ex", 10000); memberRepository.save(memberA); memberRepository.save(memberEx); //when assertThatThrownBy(() -> memberService.accountTransfer(memberA.getMemberId(), memberEx.getMemberId(), 2000)) .isInstanceOf(IllegalStateException.class); //then Member findMemberA = memberRepository.findById(memberA.getMemberId()); Member findMemberEx = memberRepository.findById(memberEx.getMemberId()); //memberA의 돈이 롤백 되어야함 assertThat(findMemberA.getMoney()).isEqualTo(10000); assertThat(findMemberEx.getMoney()).isEqualTo(10000); } } 다음과 같이 @Autowired를 쓰면 밑줄이 떠서 찾아보니 PrototypeBean과 ClientBean에 @Component를 붙이면 해결된다고 합니다. PrototypeBean과 ClientBean에 대해서는 아는게 없어서 GPT에 물어봤는데 PrototypeBean과 ClientBean을 정의하고 @Component와 @Scope를 붙히면되고, Spring 컨테이너 설정은 @ SpringbootAplication 이 붙은 클래스가 있는 경우를 전제하에 설명해줬습니다. 마지막에 프로토타입빈을 주입받아서쓰면된다고 합니다. 막혔던 부분은 일반적으로 애플리케이션의 PrototypeBean과 ClientBean을 정의하는 코드는 @SpringBootApplication 클래스가 위치한 패키지와 그 하위 패키지 내에 배치해야만 한다는데 따로 @ SpringbootAplication이 있는 클래스가 없는데 새로 만들어야되는지 모르겠어요ㅠ 마찬가지로 spring컨테이너 설정도 @ SpringbootAplication을 전제하에 설명하는데 지금 코드에 관련 애노테이션은 @SpringBootTest만 있는데 전혀 감이 잡히질 않습니다ㅠ
테스트 코드는 오류 없이 초록불이 뜨는데 DB 내 테이블 생성이 안 됩니다. 강사님의 다른 강의와, 응용 프로젝트를 만들어 볼 땐 잘 됐어서 자주 묻는 질문들을 참고해도 어느 곳이 문제인지 잘 모르겠네요ㅠㅠ.. 일단 올려두고 계속 방법을 찾아보겠습니다! package jpabook.jpashop; import org.assertj.core.api.Assertions; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import static org.junit.Assert.*; @RunWith(SpringRunner.class) @SpringBootTest public class MemberRepositoryTest { @Autowired MemberRepository memberRepository; @Test @Transactional @Rollback(false) public void testMember() throws Exception{ //given Member member = new Member(); member.setUsername("memberA"); //when //ctrl+alt+v 변수 뽑기 Long saveId = memberRepository.save(member); Member findMember = memberRepository.find(saveId); //then Assertions.assertThat(findMember.getId()).isEqualTo(member.getId()); Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername()); Assertions.assertThat(findMember).isEqualTo(member); //JPA 엔티티 동일성 보장 } } spring: application: name: jpashop #port번호 설정 server: port: 8050 #DB datasource: url: jdbc:h2:tcp://localhost/~/jpashop username: sa password: driver-class-name: org.h2.Driver #JPA jpa: hibernate: ddl-auto: create properties: hibernate: show_sql: true format_sql: true logging: level: org.hibernate.SQL: debug org.hibernate.orm.jdbc.bind: trace
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. gradlew build를 하면 계속 오류가 떠서 게시판 글들을 살펴보았는데요. V3 실시간 검사를 해제하면 된다는 이야기가 있길래 해보려고 했는데, 비밀번호가 걸려있어서 실시간 검사 해제가 안 됩니다..인터넷 검색을 해도 비밀번호를 찾는 방법은 안 나오네요. 이거 때문에 지금 이틀 동안 진도가 안 나가는데 어떻게 해야 할까요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 상품 수정 화면에서 수정 취소를 할 때, 컨트롤러를 사용하지 않고 단순 html 에서 버튼으로 경로를 지정해 주어서 상품 화면으로 이동합니다. 이 때 상품 화면을 랜더링할 때 model에 담거나 할 필요가 없는 이유가 이미 이전에 아래의 컨트롤러 @GetMapping("/{itemId}") public String item(@PathVariable Long itemId, Model model) { Item item = itemRepository.findById(itemId); model.addAttribute("item", item); return "basic/item"; } 를 통해서 해당 경로에 값이 다 담긴 상태가 저장되기 때문 이라고 생각하면 될까요? 저장된다면 어디에 저장되는 걸까요
WAS에서 request, response 객체를 만들어서 서블릿의 파라미터로 넘기는건 이해했는데 여기서 request 객체엔 요청 정보가 담겨있고 response 객체는 빈 객체인 상태인가요? 한 마디로 응답 메세지는 서블릿 컨테이너나 혹은 종료 후 다시 WAS 서버에 response 객체가 도달했을 때 정보가 들어간다고 보면 될까요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] MessageSourceTest 파일을 실행했을 때 오류가 발생합니다. Expecting: <"??"> to be equal to: <"안녕"> but was not. Expected :"안녕" Actual :"??" <Click to see difference> org.opentest4j.AssertionFailedError: Expecting: <"??"> to be equal to: <"안녕"> but was not. at java.base/java.lang.reflect.Constructor.newInstanceWithCaller( Constructor.java:500 ) at hello.itemservice.message.MessageSourceTest.helloMessage( MessageSourceTest.java:20 ) at java.base/java.util.ArrayList.forEach( ArrayList.java:1511) at java.base/java.util.ArrayList.forEach (ArrayList.java:151 1) 2024-08-16 16:42:56.803 INFO 7205 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor' MessageSourceTest > helloMessage() FAILED org.opentest4j.AssertionFailedError at MessageSourceTest.java:20 2 tests completed, 1 failed > Task :test FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':test'. > There were failing tests. See the report at: file:///Users/yujihun/Desktop/message-start/build/reports/tests/test/index.html * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 3s 4 actionable tasks: 2 executed, 2 up-to-date 도저히 원인을 모르겠어요
@WebServlet(name = "helloServlet", urlPatterns = "/hello") public class HelloServlet extends HttpServlet {} HelloServlet 가 서블릿이고, 스프링부트 실행시 서블릿의 객체가 생성되는것 같은데 name = "helloServlet" 가 의미하는것은 무엇인가요?? 서블릿 객체 이름을 의미하는건가요? 아니면 그냥 서블릿 식별자 정도 인가요??
MyLinkedListV3 stringList = new MyLinkedListV3<>(); 에서는 <> 가 있어야 하는데 왜 MyLinkedListV3 stringList = new MyLinkedListV3[CAPACITY]; 에서는 <> 를 쓰면 안되는지 궁금합니다.
2:30 를 보면 영한님께서 해시 테이블에서 Linkedlist 를 전체 버킷의 컨테이너로 사용하셨는데, ArrayList 를 전체 버킷의 컨테이너로 사용해도 전혀 문제가 없지 않나요 ? 따라서, 해시 테이블에서 ArrayList 를 전체 버킷의 컨테이너로 사용하고, 각 버킷 내에서는 LinkedList 를 사용해 충돌을 처리하는 방법도 괜찮지 않나요 ?
안녕 하세요. 궁금증이 생겨서 질문을 남깁니다. 공식 서포터즈님들의 댓글 들을 보다가, "이분 들은 강의를 완강하는데 얼마나 걸리까?"라는 생각을 하게 되었습니다. 뜬금없는 질문이긴 합니다만, 만약에 시간의 여유가 아주 넘쳐 난다면 , 공식 서포즈님들 이나, 정식 개발자 분들(개발자로 취직하신 분이시거나 프리랜서 등등)은, 영한님의 강의 중급1편, 중급 2편을 완강(체득 포함)하는데 시간이 얼마나 걸리나요? 답변 부탁 드립니다.