티스토리 뷰
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]
'기타' 카테고리의 다른 글
Java 기반 Spring설정(1) - ApplicationContext설정 (0) | 2019.11.29 |
---|---|
메세지 지향 미들웨어(Message-Oriented-Middleware) (1) | 2019.05.23 |