묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결
ptional<Item> findById 질문
@Override public Optional<Item> findById(Long id) { String sql = "select id, item_name, price, quantity from item where id = :id"; try { //Map<String, Object> param = Map.of("id", id); Map<String, Object> param = new HashMap<>(); param.put("id",id); Item item = template.queryForObject(sql,param,itemRowMapper()); return Optional.of(item); }catch (EmptyResultDataAccessException e) { return Optional.empty(); } }Map.of를 쓰지않고 그냥 new HashMap을 사용했을때 저런식으로 코드를 짜면 될까요 ?
-
미해결
트랜잭션 전파 활용5 - 전파 롤백 에서 질문 있습니다.
/** * MemberService @Transactional:ON * MemberRepository @Transactional:ON * LogRepository @Transactional:ON Exception */ @Test @Transactional void outerTxAllOn_logging_fail() { // 포함된 트랜잭션중 하나라도 런타임 에러가 발생한다면? 전체롤백!, (런타임 에러 기준임.) (체크드 예외는 커밋임) //given String username = "outerTxAllOn_logging_fail"; String username2 = "로그예외"; //when // memberService.joinV1(username); memberService.joinV2(username2); // 예외발생 log.info("--- joinV2 호출 종료"); System.out.println("겟겟 "+memberRepository.find(username2).get().getUsername()); System.out.println("겟겟 "+logRepository.find(username2).get().getMessage()); // assertTrue(memberRepository.find(username2).isPresent()); // assertTrue(logRepository.find(username2).isEmpty()); // 결과적으로 여기메소드안의 작업은 전부 롤백은 된다. }질문 1. 위 소스에서 트랜잭션이 끝나기 전에 memberRepository.find(username2) 를 수행했다면, 영속성 컨텍스트에 있던 insert들이 물리 트랜잭션에 수행되면서, 값이 조회가 되는 것이 맞는지 궁금합니다.로그로 돌려봤을땐 값이 조회가 되었습니다.질문 2. 물리 트랜잭션이 롤백되는 것이 핵심이며, 트랜잭션이 진행 중 런타임 에러가 예외로 처리되었기에, 트랜잭션이 끝나기 전 까지는 rollback()이 물리적으로 일어나지 않은 상태일 것입니다.저는 강의랑 조금 다르게 서비스에 @Transactional을 넣지 않고, 테스트 메소드에 @Transactional을 넣어 봤습니다.만약 이 상황에서 select를 날린다면, 물리 트랜잭션이 끝나지 않은(rollback되지 않은 상태)이므로 그 사이에 입력된 값은 조회가 되어야 하는게 맞아 보입니다. 이를 위해 앤티티매니저에서 flush()가 일어나고, 영속성 컨택스트에 대기중인 Insert문이 물리트랜잭션으로 전달되어 값이 조회가 되는 것으로 생각되나, 런타임 예외가 일어나서 logRepository.save(logFactory) -> em.persist(logMessage) 은 수행되지 않아야 정상일 것입니다.System.out.println("겟겟 "+logRepository.find(username2).get().getMessage());즉 위의 겟겟 logRepository.find(username2).get에서 메시지가 조회가 안 되어야 될 것입니다.그런데 log_factory에 insert문이 하이버네이트에서 생성되고, log_factory에 값이 insert된 것이 조회가 되는건지 궁금합니다. (결과적으로 롤백은 되겠지만, 트랜잭션이 끝나기 전, 왜 저 find가 정상인건지 궁금합니다.)public void joinV2(String username) { // 로그 저장 실패하면, throw 되는건 피하기 위해 Member member = new Member(username); LogFactory logFactory = new LogFactory(username); // logFactory 객체 만드는이유? logFactory객체에 (username 정보) 저장하려고. log.info("--- memberRepository 호출 시작"); memberRepository.save(member); log.info("--- memberRepository 호출 종료"); try { // 로그저장 실패한다해도 예외 안던지기 위해 직접처리 log.info("===--- logRepository 호출 시작"); logRepository.save(logFactory); log.info("===--- logRepository 호출 종료"); } catch (RuntimeException e) { log.info("로그 저장 실패, logRepository={}",logFactory.getMessage()); log.info("로그 저장 실패, ErrorMessage={}",e.getMessage()); } log.info("--- joinV2 종료"); } @Transactional public void save(LogFactory logMessage) { log.info("log 저장"); em.persist(logMessage); if (logMessage.getMessage().contains("로그예외")) { log.info("log 저장시 예외 발생"); throw new RuntimeException("예외 발생"); } }김영한님 강의 스프링 DB2편 - 데이터 접근기술에서트랜잭션 전파 활용5 를 보면서 테스트를 하다가 도저히 이해가 안가 이렇게 글을 남깁니다.설명이 너무 어려운게 아니었는지 죄송스럽습니다.