본문 바로가기
스프링과 JPA 기반 웹 어플리케이션 개발/1부 (개발환경, 회원가입, 로그인, 계정설정)

21. Open EntityManager (또는 Session) In View 필터

by Backchus 2020. 4. 21.

JPA EntityManager(영속성 컨텍스트)를 요청을 처리하는 전체 프로세스에 바인딩 시켜주는 필터.

  • 뷰를 랜더링 할때까지 영속성 컨텍스트를 유지하기 때문에 필요한 데이터를 랜더링 하는 시점에 추가로 읽어올 수 있다.(지연 로딩, Lazy Loading)
  • 엔티티 객체 변경은 반드시 트랜잭션 안에서 할 것
    • 그래야 트랜잭션 종료 직전 또는 필요한 시점에 변경 사항을 DB에 반영

현재 버그

회원가입후 이메일인증을 한 후에도 DB에 반영이 되지 않는다.

  • 컨트롤러에서 데이터를 변경했다. 왜 DB에 반영되지 않았을까?
    • 트랜잭션 범위 밖에서 일어난 일이기 때문에!

 

서비스에서 트랜잭션 관리하는 경우

 

Repository 직접 사용하는 경우

 

스터디올래의 선택

  • 데이터 변경은 서비스 계층으로 위임해서 트랜잭션안에서 처리한다.
  • 데이터 조회는 Repository 또는 서비스를 사용한다.

 

AccountController에서 이메일 인증을 하는 checkEmailToken핸들러 수정

package me.weekbelt.studyolle.account;

@RequiredArgsConstructor
@Controller
public class AccountController {

    // 기존 코드 .......
    
    @GetMapping("/check-email-token")
    public String checkEmailToken(String token, String email, Model model) {
        // 입력받은 이메일에 대한 유저가 있는지 확인
        Account account = accountRepository.findByEmail(email);
        String view = "account/checked-email";
        if (account == null) {
            model.addAttribute("error", "wrong.email");
            return view;
        }

        // 이메일은 있지만 토큰 값이 다른지 확인인
       if(!account.isValidToken(token)){
            model.addAttribute("error", "wrong.token");
            return view;
        }

//       account.completeSignUp();                  // 삭제
//       accountService.login(account);             // 삭제
       accountService.completeSignUp(account);      // 추가
       model.addAttribute("numberOfUser", accountRepository.count());
       model.addAttribute("nickname", account.getNickname());

       return view;
    }

    // 기존 코드 .........
}

 

AccountService에서 completeSignUp메소드 추가

package me.weekbelt.studyolle.account;

@Transactional                    //추가				
@RequiredArgsConstructor
@Service
public class AccountService implements UserDetailsService {
    
    // 기존 코드 ....
    
    @Transactional(readOnly = true)     // 추가
    @Override
    public UserDetails loadUserByUsername(String emailOrNickname) throws UsernameNotFoundException {
        Account account = accountRepository.findByEmail(emailOrNickname);
        if (account == null) {
            account = accountRepository.findByNickname(emailOrNickname);
        }

        if (account == null) {
            throw new UsernameNotFoundException(emailOrNickname);
        }

        return new UserAccount(account);
    }

    // 추가
    public void completeSignUp(Account account) {
        account.completeSignUp();
        login(account);
    }
}

 

 

 

참고: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1#

 

스프링과 JPA 기반 웹 애플리케이션 개발 - 인프런

이 강좌에서 여러분은 실제로 운영 중인 서비스를 스프링, JPA 그리고 타임리프를 비롯한 여러 자바 기반의 여러 오픈 소스 기술을 사용하여 웹 애플리케이션을 개발하는 과정을 학습할 수 있습니다. 이 강좌를 충분히 학습한다면 여러분 만의 웹 서비스를 만들거나 취직에 도움이 될만한 포트폴리오를 만들 수 있을 겁니다. 활용 웹 개발 프레임워크 및 라이브러리 Java Spring Spring Boot Spring Data JPA Thymeleaf 온라인 강의 스

www.inflearn.com