Spring 20

트랜잭션의 EntityManager 관리방법과 Bean으로 주입받는 EntityManger의 관리방식

1. 트랜잭션의 EntityManager 관리방법서비스 단에 @Transactional이 붙은 메서드 호출이 되면 Spring AOP 프록시가 요청을 가로채고, TransactionIntercepter를 호출한다.이 TransactionIntercepter에는 invoke 메서드가 위와 같이 구현되어 있다. 내부적으로 invokeWithinTrasaction 메서드를 실행시키고 이 내부를 들여다 보면위와 같은 코드가 들어있다.위 코드는 내부적으로 TransactionManager를 사용하며, jpa의 경우 JpaTransactionManager를 사용한다.그리고 JpaTransactionManager는 내부적으로 트랜잭션을 시작하기 위해 doGetTransaction() 메서드를 호출한다. doGetTr..

Spring 2025.02.22

EntityManagerFactory, EntityManager, 영속성 컨텍스트와 영속성 컨텍스트의 특징

[목차]EntityManagerFactory란?EntityManager란?영속성 컨텍스트란?영속성 컨텍스트의 생명주기영속성 컨텍스트의 주기능영속성 컨텍스트의 특징트랜잭션 안이 아니면 영속성 컨텍스트로 관리되지 않는다.영속성 컨텍스트는 Map으로 관리되며 key는 기본키를 사용한다. [본론]EntityManagerFactory란?EntityManagerFactory란 EntityManager를 생성하는 역할을 한다.Spring Application이 실행될 때 딱 한번만 생성되며, 이 후 EntityManager가 필요하면 같은 EntityManagerFactory를 사용하여 생성한다.딱 한 번만 생성하는 이유는 생성비용이 크기 때문이다.한 EntityManagerFactory는 여러 EntityManag..

Spring 2025.02.22

영속성 컨텍스트의 1차 캐시는 어떻게 저장될까?

영속성 컨텍스트의 1차 캐시1차 캐시는 Map 형태로 관리된다.이는 Hibernate의 PersistenceContext 의 구현체인 StatefulPersistenceContext 에서 찾아볼 수 있다.entitiesByKey 필드 등을 보면 PK를 Key로 Object(엔티티)를 value로 관리하는 것을 볼 수 있다. 그리고 이 Key는 기본키를 저장한다따라서 findById가 호출되면 내부적으로 우선 Map을 확인해 엔티티가 존재하는 지 확인하며, 있으면 Map에서 반환한다. 없으면 DB를 조회하여 Map 저장하고 엔티티를 반환한다. 만약 findByName() 등을 통해 조회하면 Name은 기본키가 아니므로 DB에서 조회해오게 된다. DB에서 조회해온 후에는 조회한 ID를 통해 같은 엔티티가 영..

Spring 2025.02.22

@Transactional 내에서가 아니여도 OSIV가 on이면 조회한 데이터들이 같은 영속성 컨텍스트를 공유하는 이유

[서론]스프링에서는 트랜잭션이 시작되면 AOP 코드에 따라 내부적으로 EntityManager를 사용해 영속성컨텍스트를 만들어, 한 트랜잭션 내에서는 같은 영속성컨텍스트를 공유하게 끔 동작합니다. 진짜 그럴까 테스트해보면, 종종 @Transactional이 붙지 않았는데도 데이터들이 한 영속성 컨텍스트에서 공유되는 것을 볼 수 있습니다. 예를 들어 다음과 같이 id가 1인 객체를 두 번조서론]스프링에서는 트랜잭션이 시작되면 AOP 코드에 따라 내부적으로 EntityManager를 사용해 영속성컨텍스트를 만들어, 한 트랜잭션 내에서는 같은 영속성컨텍스트를 공유하게 끔 동작합니다.   진짜 그럴까 테스트해보면, 종종 @Transactional이 붙지 않았는데도 데이터들이 한 영속성 컨텍스트에서 공유되는 것을..

Spring 2025.02.22

@Profile과 @ActiveProfile

@Profile과 @ActiveProfileapplication.properties or yml에서 어떤 프로필을 사용할 지 결정할 수 있다.spring.profiles.active=dev,local 이라고 명시하면 dev 프로필과 local 프로필을 사용하게 된다.반면 Spring 코드 내에서 운영 환경에 따라 다른 빈을 주입해야 할 수도 있다.메인 환경에서는 RedisMainConfig를 개발환경에서는 RedisDevConfig를 사용해 서로 다른 캐시를 사용해야 할 수도 있다.또한 테스트 환경에서는 특정 프로필과 다른 프로필을 사용해야 할 수있다.이럴 경우 @Profile 혹은 @ActiveProfile을 사용할 수 있다.1. @Profile@Profile은 환경에 따라 Bean의 로딩을 다르게 할..

Spring 2025.02.20

LazyInitializationException과 LazyLoading의 동작원리

@Transactional이 붙지 않은 메서드 내에서 LazyLoading된 필드를 접근 시 하이버네이트가 LazyInitializationException을 발생시킨다.왜냐하면 Lazy Loading이 동작하려면 영속성 컨텍스트가 필요하지만, 이게 닫혀있기 때문이다.그럼 Hibernate는 어떻게 이를 알아챌까?Lazy Loading의 동작과정LazyLoading은 프록시 객체를 사용해서 동작한다.특정 엔티티가 LazyLoading이 붙은 필드가 있다면, Hibernate는 이 엔티티의 프록시 객체를 생성한다.class Room$HibernateProxy extends Room { private List places = new PersistentBag(); // Lazy Loading Proxy}..

Spring/Spring Jpa 2025.02.19

Spring에서의 예외, 에러 처리

Spring을 사용하다가 @RestControllerAdvice 를 사용하지 않으면 Spring에서 어떻게 예외를 처리하는 지 궁금해졌다. 그래서 이에 대해 알아보고자 한다.Spring의 기본 예외 핸들링1. BasicErrorControllerSpring의 기본 예외 처리는 공식 문서를 통해 알 수 있었다.기본적으로 모든 예외가 발생하면 /error 경로로 Spring이 재요청하여 기본적으로 등록되어 있는 BasicErrorController에서 예외 응답을 반환한다고 한다. 컨트롤러에서 BasicErrorController로의 예외 전달Spring Boot에서 예외가 발생되고, @RestControllerAdvice 및 @ExceptionHandler 에서 예외가 처리되지 않으면 에러가 처음 요청을 ..

Spring 2024.11.02

Spring에서의 프로세스와 스레드

프로세스와 스레드만약 프로세스와 스레드에 관한 지식이 부족하다면 아래 포스트를 참고해도 좋을 거 같습니다.https://yooooonshine.tistory.com/43Spring에서의 프로세스와 스레드Spring 서버는 서버 자체로 하나의 프로세스이기 때문에, 내부 동작은 프로세싱과 거의 무관하다.대신 Spring은 멀티 스레딩 개념을 활용하여 성능 최적화를 한다.만약 멀티 프로세싱 개념을 통해 병렬 처리를 하고 싶다면, 컨테이너 기반 배포 환경을 공부하는 것이 좋을 거 같다.Spring의 스레드스프링에서는 스레드 개념을 어디서 사용하고 있을까?대략 아래와 같은 부분에서 사용하고 있다고 한다.스레드 풀비동기 작업트랜잭션 관리이것들을 중심으로 어떻게 사용되고 있는 지 알아보고자 한다.스레드 풀(threa..

Spring 2024.10.21

@ManyToMany를 사용하면 안 되는 이유

@ManyToMany 를 실무에서 사용하면 안된다는 얘기를 많이 들었고, 그래서 항상 관계를 풀어서 사용했었다.이번에 다시 관계를 풀어 사용하면서 왜 풀어야하나 생각해보니 답이 떠오르지 않아 이를 정리해본다.@ManyToMany@Entitypublic class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToMany @JoinTable( name = "student_course" // 중간 테이블의 이름 ) private List courses = new ArrayList(); // 기본 생성..

Spring/Spring Jpa 2024.10.15