3) JPA 설정

  • Mybatis 설정이 완료된 프로젝트 이후에 JPA 설정을 추가합니다.
  • 먼저 build.gradle에 다음 라이브러리를 추가하고 코끼리 버튼을 클릭하여 업데이트합니다.
dependencies {
    
    ...
    // JPA 라이브러리 추가 (기존에 있으면 추가안해도 무방함)
    implementation 'org.springframework.data:spring-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    ...
}

  • 그런 다음 application.properties 파일을 수정합니다.
(기존 내용 아래 추가)
teamflace.jpa.datasource.master.jdbc-url=jdbc:log4jdbc:mysql://localhost:3306/(스키마명)?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&autoReconnection=true
teamflace.jpa.datasource.master.username=(아이디)
teamflace.jpa.datasource.master.password=(비밀번호)
teamflace.jpa.database=mysql
teamflace.jpa.hibernate.use-new-id-generator-mappings=false
teamflace.jpa.show-sql=true
#데이터베이스 방언을 프로젝트 main DB인 MySQL로 설정
teamflace.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
#JPA Lazy 타입 조회 시, N+1(1+N) 현상 발생 방지
teamflace.jpa.properties.hibernate.default_batch_fetch_size=1000

  • 이제 구성 파일의 내용을 Spring 컨테이너에 주입하기 위한 구성 파일을 만들어야 합니다.
  • 먼저 위에서 만든 구성 패키지 아래에 JpaConfig.java 파일을 만듭니다.
  • 미리 저장소 패키지 아래에 jpa 패키지를 생성해야 합니다(JPA 설정을 적용할 패키지 지정).
  • @EnableJpaRepositories(basePackages = “com.example.settingtest.repository.jpa”에 저장소가 저장된 위치를 입력합니다.
  • em.setPackagesToScan(“com.example.settingtest.domain”); 실제 엔터티가 저장된 패키지를 입력합니다.


(임포트 구문 생략)

@Configuration
@Lazy
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.example.settingtest.repository.jpa", entityManagerFactoryRef = "teamfleshEntityManagerFactory")
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class JpaConfig {

    private Logger log = LogManager.getLogger(this.getClass());

    private Properties properties;

    @Autowired
    public JpaConfig(@Qualifier("teamfleshDatasourceProperties") Properties properties) {
        this.properties = properties;
    }
    
    //application.properties 파일에 teamflace.jpa로 시작하는 접속 정보를 Properties에 가져온다.
    @ConfigurationProperties(prefix = "teamflace.jpa")
    @Bean(name = "teamflaceJpaDataSourceProperties")
    public Properties teamflaceJpaDataSourceProperties() {
        return new Properties();
    }
    
    //위에서 만들어진 properties 정보를 바탕으로 spring JDBC에 필요한 dataSource를 생성
    @Bean(name = "teamflaceJpaDatasource")
    public DataSource teamflaceJpaDatasource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        log.info("teamflaceJpaDatasource  ===> {}", dataSource);
        dataSource.setDriverClassName(properties.getProperty("driver-class-name"));
        dataSource.setUrl(properties.getProperty("url"));
        dataSource.setUsername(properties.getProperty("username"));
        dataSource.setPassword(properties.getProperty("password"));

        return dataSource;
    }
    
    //위에서 만들어진 datasource를 바탕으로 JPA에 영속성 컨텍스트인 EntityManager를 만든다.
    @Bean(name = "teamfleshEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean teamfleshEntityManagerFactory() throws Exception {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(teamflaceJpaDatasource());
        em.setPackagesToScan("(실제 entity가 저장되는 패키지)");
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(teamflaceJpaDataSourceProperties());
        log.info("teamflaceJpaDataSourceProperties ===> {}", teamflaceJpaDataSourceProperties());

        return em;
    }
    
    //Mybatis와 같이 사용하기 위해 작업을 한 트랜잭션으로 묶기 위한 배경작업
    @Bean(name = "teamflaceJpaTransactionManager")
    public PlatformTransactionManager teamflaceJpaTransactionManager() throws Exception {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(teamfleshEntityManagerFactory().getObject());
        log.info("teamflaceJpaTransactionManager  ===> {}", transactionManager);
        return transactionManager;
    }         
}

  • 이제 Mybatis 설정에서 생성한 RdbConnectionConfiguration을 변경하여 Mybatis와 하나의 트랜잭션으로 관리합니다.
임포트 구문 생략)
@Configuration
@Lazy
@EnableTransactionManagement
public class RdbConnectionConfiguration {

    @Bean(name = "transactionManager")
    @Primary
    public PlatformTransactionManager transactionManager(
            @Qualifier("mybatisTransactionManager") PlatformTransactionManager mybatisTransactionManager,
            @Qualifier("teamflaceJpaTransactionManager") PlatformTransactionManager teamflaceJpaTransactionManager) {
        return new ChainedTransactionManager(
                mybatisTransactionManager,
                teamflaceJpaTransactionManager);
    }
}

  • JPA 구성이 완료되고 테스트 코드에서 테스트가 수행됩니다.
  • 아래 위치에 리포지토리 파일을 추가합니다.


@Repository
public interface MemberJpaRepository extends JpaRepository<Member, Long> {
    Member findByEmail(String email);
}
  • 기존 엔터티에 @Entity 및 @Id 특성을 추가합니다.


테스트 코드 작성

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
@Transactional
class MemberJpaRepositoryTest {

    @Autowired
    MemberJpaRepository memberJpaRepository;

    @BeforeEach
    public void setUp() {
        //setup before testing
        memberJpaRepository.deleteAll();
    }

    @Test
    @DisplayName("이메일로 멤버 조회 JPA 테스트")
    void findByEmail() {
        //given : 멤버 정보가 주어졌을 때
        Member member = new Member();
        member.setEmail("[email protected]");
        member.setName("배이든");
        member.setAddress("경기도 부천");
        member.setPassword("1123");

        memberJpaRepository.save(member);

        //when : 이메일로 단건조회를 하면
        Member memberResult = memberJpaRepository.findByEmail("[email protected]");

        //then : 해당 유저 정보를 조회할 수 있다.
        assertThat(memberResult.getId()).isGreaterThanOrEqualTo(1);
        assertThat(memberResult.getEmail()).isEqualTo("[email protected]");
        assertThat(memberResult.getName()).isEqualTo("배이든");
        assertThat(memberResult.getAddress()).isEqualTo("경기도 부천");
        assertThat(memberResult.getPassword()).isEqualTo("1123");

    }
}


  • JPA 설정이 완료된 것을 확인할 수 있습니다.