Member
package hello.springtx.propagation;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.Setter;
@Entity
@Getter @Setter
public class Member {
@Id
@GeneratedValue
private Long id;
private String username;
public Member() { // 기본 생성자는 jpa 스펙상 무조건 무조건 무조건 있어야한다.
}
public Member(Long id) {
this.id = id;
}
}
JPA를 통해 관리하는 회원 엔티티이다.
MemberRepository
package hello.springtx.propagation;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@Slf4j
@Repository
@RequiredArgsConstructor
public class MemberRepository {
private final EntityManager em;
@Transactional // jpa의 모든 변경은 트랜잭션 안에서 이루어져야만 한다.
public void save(Member member) {
log.info("member 저장");
em.persist(member);
}
public Optional<Member> find(String username) { // (먼저 1개 걸리면) 만약 값이 없으면 옵셔널 안에 엠프티기 ㅇㅣㅆ음
return em.createQuery("select m from Member m where m.username = :username", Member.class)
.setParameter("username", username)
.getResultList().stream().findAny(); // 만약에 결과가 2개가 나왔으면 그 둘 중에 1개만 찾아서 반환해주는 것이다.
}
}
JPA를 사용하는 회원 리포지토리이다. 저장과 조회 기능을 제공한다.
Log
package hello.springtx.propagation;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.Setter;
@Entity // 데이터 베이스에 남겨놓는 로그이다.
@Getter @Setter
public class Log {
@Id // 이어노테이션만 되어있으면 jpa에서는 내가 id를 직접 할당해줘야한다.
//@Getter 실수.
@GeneratedValue // db에서 뭐 할당하거나 아니면 값을 할당하는걸 사용하게 된다.
private Long id;
private String message;
// jpa 쓰려면 기본 생성자는 필수임.
public Log() {}
public Log(String message) {
this.message = message;
}
}
JPA를 통해 관리하는 로그 엔티티이다.
LogRepository
package hello.springtx.propagation;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@Slf4j
@Repository
@RequiredArgsConstructor
public class LogRepository {
private final EntityManager em;
@Transactional // 이 트랜잭션을 그 aop 프록시에서 트랜잭션 프록시에서 어떻게 하면 여기 메서드에서 런타임 익셉션이네. 롤백하면서 이 메서드 부분이 롤백 된다.
public void save(Log logMessage) {
log.info("log 저장");
em.persist(logMessage);
// 예외상황 만듦
if (logMessage.getMessage().contains("로그예외")) {
log.info("log 저장시 예외 발생");
throw new RuntimeException("예외 발생");
}
}
public Optional<Log> find(String message) {
return em.createQuery("select l from Log l where l.message = :message", Log.class)
.setParameter("message", message)
.getResultList().stream().findAny();
}
}
로그예외
라고 입력하는 경우 예외를 발생시킨다.MemberService