10. 트랜젝션,로그아웃

박선규's avatar
Jan 29, 2024
10. 트랜젝션,로그아웃
💡
table 테이블=릴레이션=NTT 이렇게 3개의 명칭이 있다. 로우, 레코드 2가지 명칭이 있다.
 

@Transactional

📌
트랜잭션 관리: @Transactional이 붙은 메소드는 실행이 시작될 때 새로운 트랜잭션이 시작됩니다. 만약 이미 트랜잭션이 진행 중이라면 그 트랜잭션에 참여하게 됩니다.
롤백(Rollback): @Transactional 어노테이션이 붙은 메소드에서 예외가 발생하면, 해당 트랜잭션은 롤백됩니다. 이는 데이터의 일관성을 유지하는 데 중요한 역할을 합니다.
커밋(Commit): @Transactional 어노테이션이 붙은 메소드가 정상적으로 종료되면, 해당 트랜잭션은 커밋되어 데이터베이스에 반영됩니다.격리 수준(Isolation Level) 설정: 트랜잭션의 격리 수준을 설정하여 동시에 여러 트랜잭션이 처리될 때 발생할 수 있는 문제를 방지할 수 있습니다.
 

트랜잭션

📌
트랜잭션은 데이터베이스에서 데이터를 처리하는 하나의 논리적인 작업 단위를 의미합니다
원자성(Atomicity): 트랜잭션 내의 모든 연산이 완전히 수행되거나, 아니면 전혀 수행되지 않아야 함을 의미합니다. 즉, 중간 단계까지만 수행되는 상황은 없어야 합니다. 만약 중간에 오류가 발생하면 이전 상태로 되돌립니다. 일관성(Consistency): 트랜잭션이 성공적으로 완료되면 항상 일관된 데이터베이스 상태를 유지해야 함을 의미합니다. 독립성(고립성)(Isolation): 각 트랜잭션은 서로 독립적이어야 함을 의미합니다. 즉, 여러 트랜잭션이 동시에 실행되더라도 서로에게 영향을 주어서는 안됩니다. 영속성(Durability): 트랜잭션이 성공적으로 완료된 후에는 결과가 영구적으로 반영되어야 함을 의미합니다.
📌
클라이언트 3명 → 서버 → DB
read는 동시에 들어와도 되지만 Write가 들어오면 이상한 일이 발생한다!
3명이 동시에 들어왔다
cos로 회원가입 하고 싶다!
3명이 동시 cos를 insert(Write) 하지만 insert는 락이 걸린다. 동시에 들어와도 rock이 걸림 → 이걸 아이솔레이션이라 한다. 아이솔레이션이 걸리면서 정확성이 떨어지지 않도록 무결성이 생기지 않도록 고립시켜 버린다.
변형을 주는 요청은 고립이 된다. (Update Delete insert) → 자제하는 것이 좋다 느리게 만드니깐
이로 인해 검증을 하고 insert를 시켜준다.
트랜젝션이 요청하고 응답하면 종료된다.
길게 끌고 갈 수 있다. → 쥐고 있는 것이 가능하다 (프로그램적으로 가능한데 이러는 이유는?) → Write를 여러번 해야하는 경우! ex) 이체(한 계좌에서만 금액 변경이 일어 날수 있다) 등
 
업데이트는 메모리만 변경 되기 때문에 commit을 한다 영구히 기록하기 위해서!
입금은 update 한방에 끝난다! (트랜젝션이 하나의 업데이트!)
이체는 update 2번이 하나의 트랜젝션이다!
트랜젝션은 상대적인 의미이다!
 
ex) -1 떨어지면 모두 롤백
트랜젝션이 일어나면 모든 트랜젝션이 메모리에 걸려있다.
롤백 : 언두에 있는 데이터를 덮어 씌움. (원자성)
 
 
 

실패하는 트랜젝션을 만들면 안된다!!

 
비지니스코드 → DB에 ID가 있는지 없는지 확인하고 회원가입 시켜줄지 말지를 결정하는 코드.
DB는 하드에 저장된 데이터가 어디에 저장 되어있는지 알려주는 문서를 가지고 있다. (IO가 일어 나진 않지만 통신은 일어난다)
데이터 딕셔너리 (메타 데이터 같은 것, 데이터 사전)
 
트라이캐치는 어쩔수 없을떄 쓰는것
터트릴수 없는 방법이 있으면 최대한 미리 안 터트리기 조회를 할 수 있으면 조회 한번 하고 미리 안 터트리기\
→ 최대한 문제가 생길 것 같으면 인서트를 줄여야함 (다른 놈이 고립이 걸리기 때문에)
 
 
리드 할때부터 트랜젝션으로 걸면 아무도 못먹음
 
서비스 레이어 : 트랜젝션을 관리하는(묶는) 레이어 → 최소한의 단위를 트랜젝션으로 묶을수 있다.
package shop.mtcoding.blog.user; import org.springframework.stereotype.Repository; import javax.persistence.EntityManager; import javax.persistence.Query; import javax.transaction.Transactional; @Repository // IoC에 뜬다. 내가 new를 안해도 된다. public class UserRepository { private EntityManager em; public UserRepository(EntityManager em) { this.em = em; } @Transactional // 값을 넣어주는 역할을 하는데 항상 초기화 되도록한다. public void save(UserRequest.joinDTO requestDTO) { // Query를 직접 짬 Query query = em.createNativeQuery("insert into user_tb (username, password, email) values (?, ?, ?)"); query.setParameter(1, requestDTO.getUsername()); query.setParameter(2, requestDTO.getPassword()); query.setParameter(3, requestDTO.getEmail()); query.executeUpdate(); // DB로 전송 } @Transactional public void saveV2(UserRequest.joinDTO requestDTO) { // 통신을 통해서 받은 데이터를 Entity라는 클래스로 옮김 (하이버 네이트) User user = new User(); user.setUsername(requestDTO.getUsername()); user.setPassword(requestDTO.getPassword()); user.setEmail(requestDTO.getEmail()); em.persist(user); } public User findByUsernameAndPassword(UserRequest.loginDTO requestDTO) { // 아이디 비밀번호를 입력시 DB에서 조회 Query query = em.createNativeQuery("select * from user_tb where username=? and password=?", User.class); // 타입만 적어주면 자동으로 파싱해줌 query.setParameter(1, requestDTO.getUsername()); query.setParameter(2, requestDTO.getPassword()); try { User user = (User) query.getSingleResult(); // Entity 라서 가능한 형태 return user; } catch (Exception e) { return null; } } }
얘는 어차피 다른 얘랑 같이 사용할 일이 없는 경우에 독립적인 트랜젝션으로 걸었다. save, saveV2에 트랜젝션을 거는 이유

final 붙이는 의존성 주입

  • 의존성 주입은 모두 final을 붙힌다.
👉
final이 붙은 매개변수들만 생성자로 생성하는 어노테이션은? @RequiredArgsContructor final은이 붙은 애들의 기본 생성자를 만들어줘야한다.
@RequiredArgsConstructor //final이 붙은 애들에 대한 생성자를 만들어준다. @Controller public class UserController { private final UserRepository userRepository; @PostMapping("/join") public String join(UserRequest.JoinDto requestDto) { System.out.println(requestDto); return "redirect:/loginForm"; }
notion image
notion image

save 함수 호출

@PostMapping("/join") public String join(UserRequest.JoinDTO requestDTO){ System.out.println(requestDTO); userRepository.save(requestDTO); // 모델에 위임하기 return "redirect:/loginForm"; }

h2-console 가서 값 확인하기

notion image
notion image

 
 
스프링에서 classpath는 리소스다

classpath

📌
클래스패스(Classpath)는 Java가 클래스 파일을 찾는 경로를 의미한다. 즉, Java 프로그램이 실행될 때 JVM(Java Virtual Machine)이 클래스나 패키지를 찾기 위해 참조하는 경로입니다. calsspath 문법 -classpath:db/data.sql 컬렉션은 하이픈 해서 작성하기
야물 문법(주말에보기)
 
class인데 오타남.ㅠㅠ
class인데 오타남.ㅠㅠ

jar

📌
JAR(Java ARchive) 파일은 여러 개의 Java 클래스 파일과 관련 리소스(이미지, 텍스트 등) 및 메타데이터를 하나의 파일로 압축한 것입니다. .jar 확장자를 가지며, ZIP 파일 형식을 기반으로 합니다
배포와 설치를 용이하게 함: 여러 개의 클래스 파일과 리소스를 하나의 파일로 묶어 배포하거나 설치하는 것을 쉽게 만듭니다.재사용성: 라이브러리나 API 같은 재사용 가능한 코드를 JAR 파일로 만들어 다른 프로젝트에서도 쉽게 사용할 수 있게 합니다.보안: JAR 파일 내에 디지털 서명을 추가하여 코드의 출처와 무결성을 보장할 수 있습니다.
JAR 파일은 jar 명령어를 사용하여 생성, 업데이트, 조회 등을 할 수 있습니다. 또한, 매니페스트(Manifest)라는 특별한 파일을 포함하여 JAR 파일의 메타데이터를 관리할 수 있습니다. 매니페스트 파일에는 JAR 파일의 버전 정보, 저작권 정보, 실행 가능한 클래스의 위치 등이 포함될 수 있습니다.
notion image
 
 
 
 

로그 아웃

 
로그아웃은 두가지 방법이 있는데
1.내가 키를 버리던가 (이러고 재 로그인을 하려고하면 jsession아이디가 없기때문에 session에서 새로운 서랍과 jsession키가 생긴다. 그럼 세션의 원래 세션의 키가 있는데 새로 만들게 되니 메모리를 계속 잡아먹게 되는데 이것을 해결하기 위해 세션 저장소 유효기간이 있다. 이것을 설정 할 수있다.)
 
2.세션의 서랍을 비우기 (이렇게 될 경우 세션 키 속성등 모든 내용들이 날라간다.
 
브라우저를 다 닫고 다시 웹 페이지에 들어가면 자연적 로그아웃 상태 돼있음
 
 
직접 로그아웃의 3가지 방법!
  1. 세션을 직접 날린다. ( server에서 코드로 )
  1. yml 또는 web.xml 에서 jsession의 유효기간을 설정한다 ( 지나면 로그아웃 )
  1. 브라우저 종료 ( 쿠키 직접 삭제 )
 
클라이언트가 쿠키에 있는 내용을 삭제하는데 많은 자료도 안넣는다 이유는 모두 동일 ( 공간 ) 세션 저장소 유효 기간이 존재한다. 계속 놔두면 메모리 공간을 차지 하기 때문에 유효 기간이 있다.
 
session.invalidate(); // 세션을 날려버리는 것
 
 
Request의 생명 주기는 세션 보다 짧다. (응답하고 나면 삭제 되지만 세션은 살아 있다) 반이중 통신을 stateful 하게 만드는것이 세션이다.
세션은 다음 요청을 하였을때 누구인지 알도록 해준다.
 
리퀘스트랑 세션은 메모리 관점에서 봐야된다.
 
반이중 통신을 statefull 하게 만드는게
 
리퀘스트의 생명주기는 세션 생명주기 보다 짧다.
 
 
notion image

 
게시글에는 타이틀- 서브 타이틀 필요 댓글은 다른 클레스로 뺄거임
 
 
유저가 게시글을 작성하고 게시글을 볼 수있고 작성 할 수 있고 삭제 할 수있고 (결국 블로그 만들기)
 
 
Share article
RSSPowered by inblog