티스토리 뷰

기타

Java 기반 Spring설정(2) - JPA

도리강 2019. 12. 23. 16:39

1편에서는 간단한 RootApplicationContext와 WebApplicationContext를 설정하였다면, JPA 설정기반과 Transaction 설정 위주로 진행하겠다.

 

1. JdbcTemplate Transaction 설정

 지난 포스터에서는 Transaction 설정이 빠져있어 기본적인 JdbcTemplate에 Transaction 설정부터 먼저 하겠다.

@Configuration
@EnableTransactionManagement
public class JdbcTemplateConfiguration {

    @Bean
    public NamedParameterJdbcTemplate jdbcTemplate(DataSource dataSource){
        NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
        return jdbcTemplate;
    }

    @Bean
    public PlatformTransactionManager dataSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

}

프로그래밍 방식의 트랜잭션 처리를 위하여 스프링에서 제공하는  PlatformTransactionManager 인터페이스 타입의 Bean을 등록하였다. 

@EnableTransactionManagement는 Spring의 Annotation 기반의 트랜잭션 관리 기능을 사용할 때 쓰인다. xml 기반의 "<tx:annotation-driven>과 유사한 기능이다. proxy, aop 동작기반 등을 지원하여 @Transactional을 선언한 곳에서 이러한 기능들을 지원해준다. 

 

2. Jpa 설정

@Configuration
@EnableJpaRepositories(
        basePackageClasses = MemberManagementJpaRepo.class,
        transactionManagerRef = "jpaTransactionManager")
@EnableTransactionManagement
@PropertySource("classpath:jpa.properties")
public class JpaConfiguration {

    @Autowired
    private Environment env;

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setJpaVendorAdapter(jpaVendorAdapter());
        emf.setDataSource(dataSource);
        emf.setPersistenceUnitName("persistenceJpa");
        emf.setPackagesToScan("com.domain.*");
        emf.setJpaProperties(additionalProperties());
        return emf;
    }

    private JpaVendorAdapter jpaVendorAdapter(){
        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setShowSql(true);
        return jpaVendorAdapter;
    }


    @Bean
    public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
        jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
        return jpaTransactionManager;
    }

    private Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("spring.jpa.hibernate.ddl-auto", env.getProperty("ddl-auto"));
        properties.setProperty("spring.jpa.show-sql", env.getProperty("show-sql"));
        properties.setProperty("spring.jpa.properties.hibernate.format_sql",  env.getProperty("format_sql"));
        return properties;
    }

}

 

 

1)  @EnableJpaRepositories

 Spring Data Jpa를 활성화하기 위한 어노테이션이다. basePackageClasses는 Spring Data Jpa를 사용할 클래스를 입력하면된다.

아래는 Spring Data Jpa에서 제공되는 JpaRepository를 상속한 MemberCommonRepository 클래스이다.

public interface MemberCommonRepository extends JpaRepository<Member, Long>{

    Optional<Member> findMemberByMemberEmail(String email);

}

 

 

 

 

그리고 transactionManagerRef라는 속성을 볼 수 있다. 기본적으로 Spring Data Jpa는 TransactionManager를 제공해주고 그 transactionManager에 대한 default bean 이름이 transactionManager로 되어있다. 

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({JpaRepositoriesRegistrar.class})
public @interface EnableJpaRepositories {
    //생략....

    String transactionManagerRef() default "transactionManager";

}

그래서 만약 transactionManagerRef를 지정하지 않는 상태에서 PlatformTransactionManager bean 이름을 transactionManager로 설정하면 등록이 되지만, 다른 이름으로 변경한 상태에서 application을 실행하면 "transactionManager" 이름을 찾을 수 없다는 에러가 발생한다.

transactionManagerRef의 설정한 bean 이름으로 변경해줘야 bean이 정상적으로 등록이된다.

 

2) LocalLocalContainerEntityManagerFactoryBean 등록

  해당 부분은 Springdl EntityManagerFactoryBean을 사용하기 위하여 사용된다. 

 

setPackagesToScan : Entity로 등록된 클래스 위치정보를 입력 

setJpaVendorAdapter : JPA를 구현할 벤더사 설정 부분

setJpaProperties : 'show-sql' 등 jpa와 관련된 프로퍼티 설정

 

 

3. Bean 설정 Refactoring

@Configuration
@PropertySource("classpath:datasource.properties")
@ComponentScan(basePackageClasses =
        {JdbcTemplateConfiguration.class, ......생략})
public class RootAppContextConfiguration {

}

RootApplicationContext에서 JdbcTemplateConfiguration 혹은 JpaConfiguration 클래스를 스캔 대상 중 하나만 지정해도 bean 등록이 완료된다.

 

하지만, 해당 클래스만으로 기타 다른 설정 클래스들도 스캔이 된다는걸 다른 사람이 코드를 보면 알 수 없는 문제가 발생한다. 그래서 Marker 인터페이스를 하나 두어, 해당 인터페이스 클래스를 Scan 대상으로 포함하면 좀 더 명시적(?)이고 가독성면에서 좋을 것 같아 마커 인터페이스를 두었다. 

@Configuration
@PropertySource("classpath:datasource.properties")
@ComponentScan(basePackageClasses =
        {PersistenceConfiguration.class, ......생략})
public class RootAppContextConfiguration {

}

 

4. Service Transaction 설정 부분

현재 transaction 설정은 JdbcTemplate과 JPA 두개로 나눠져 있어 이를 구분할 수 있도록 각 Service 구현체에 명시적으로 선언해줘야한다. 그래야 선언적 @Transactional이 어떤 Bean을 참고 대상으로 할지 알 수 있기 때문이다.

 

-JdbcTemplate Transactional 부분

@Service
@Transactional(transactionManager = "dataSourceTransactionManager")
public class MemberManagementJdbcImple implements MemberManagementJdbcService{

		//생략
}

 

-Jpa Transactional 부분

@Service
@Transactional(transactionManager = "jpaTransactionMangaer")
public class MemberManagementJPAImpl implements MemberManagementJPA{

		//생략
}

 

 

[Refference]

https://blog.woniper.net/258

https://docs.spring.io/

https://docs.spring.io/

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함