Skip to main content Link Search Menu Expand Document (external link)
  • 직접 EntityManager 생성하여 트랜잭션 관리 코드 샘플 작성
  • SpringBoot 에서의 JPA 아키텍처
    • JPA class 생성 흐름
    • JPA class 관계

직접 EntityManager 생성하여 트랜잭션 관리 코드 샘플 작성

아래와 같이 EntityManagerFactory 부터 생성해서 궁극적으로 트랜젝션을 시작, 종료하는 샘플 앱을 만들어보는 단원이었다.

        EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("persistenceUnitName");
        EntityManager entityManager=entityManagerFactory.createEntityManager();
        EntityTransaction transaction=entityManager.getTransaction();
        
        try{
            transaction.begin();
            // business logic
            transaction.commit();
        } catch (Exception exception) {
            transaction.rollback();
        } finally {
            entityManager.close();
        }

JPA 를 사용하면 위와 같은 EntityManager 생성 및 트랜잭션 관리가 알아서 되는 것이고, 개발자들은 이를 제대로 활용하기 위해서는 스프링에서 ‘알아서’ 해주는 그런 것들이 어떤 것들이 있는지와 어떤 과정으로 이뤄지는지를 알고 있어야 한다.

SpringBoot 에서의 JPA 아키텍처

이 사이트 에 정리가 매우 잘되어 있어서 그대로 가져왔다.

여기서 persistence unit은 아래와 같이 Database 접속 정보를 가지고 있는 configuration 이라고 보면 된다.

    <persistence-unit name="hello">
        <properties>

            <!-- 필수 속성 -->
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="javax.persistence.jdbc.user" value="berry"/>
            <property name="javax.persistence.jdbc.password" value="straw"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/jpa-practice-schema"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>

            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments" value="true"/>

        </properties>

    </persistence-unit>

위 구조에서 entityManagerFactory의 경우 Bean으로 자동 생성된다. Runner 에서 아래와 같이 직접 확인해본다.

    @Override
    @Transactional
    public void run(ApplicationArguments args) throws Exception {
        String[] beans = applicationContext.getBeanDefinitionNames();

        for (String bean : beans) {
            System.out.println("bean : " + bean);
        }

    }
...(중략)...
bean : entityManagerFactoryBuilder
bean : entityManagerFactory
...(중략)...

EntityManager 는 @PersistenceContext 를 통해서 아래와 같이 entityManagerFactory 로 생성해서 주입받아 사용한다.

    @PersistenceContext
    private EntityManager entityManager;

책에서도 강조하듯 EntityManager는 데이터 베이스 커넥션과 밀접하게 작동하므로 스레드간에 공유하거나 재사용을 하면 안된다. 아래와 같이 EntityManager 를 변수명을 달리 하여 두 개를 생성해봐도 결국 주소값을 비교해보면 동일한 EntityManager 임을 확인할 수 있다.

@Component
public class JpaRunner implements ApplicationRunner {

    @PersistenceContext
    private EntityManager entityManager1;

    @PersistenceContext
    private EntityManager entityManager2;


    @Override
    @Transactional
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(">>>>>");
        System.out.println(entityManager1);
        System.out.println(entityManager2);
        System.out.println("<<<<<");
    }

}
>>>>>
Shared EntityManager proxy for target factory [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@103478b8]
Shared EntityManager proxy for target factory [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@103478b8]
<<<<<