숑숑이의 개발일기
article thumbnail

H2 데이터베이스 설치

아래의 링크에서 1.4.200 버전을 설치한다. 

만일 이미 설치후 실행까지 했다면 ~/test.mv.db 파일을 꼭 삭제 해야한다.

https://www.h2database.com/html/download-archive.html

 

Archive Downloads

 

www.h2database.com

 

맥 사용자의 경우 cmd에서 권한주기 : chmod 755 h2.sh

실행방법

h2가 설치된 경로에 있는 bin 폴더에 들어가 아래의 명령어를 cmd에서 입력

  • 맥 : ./h2.sh
  • 윈도우 : h2.bat

 

스프링 통합 테스트

  • @SpringBootTest : 스프링 컨테이너와 테스트를 함께 실행함
  • @Transactional : 테스트 케이스에 해당 어노테이션이 존재하면 @test 어노테이션이 붙어있는 테스트 완료 후 롤백함. 해당 어노테이션을 사용하기 위해선 build.gradle에 아래의 설정이 필요하다.
    (만일 Commit하고 싶다면 @Commit 어노테이션을 붙이면 됨)
dependencies {
	runtimeOnly 'com.h2database:h2'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

 

  • 단위 테스트 : 순수 자바 코드로 하는것
  • 통합 테스트 : 스프링컨테이너와 데이터베이스까지 연동하여 테스트 하는 것
    • 절대적인 것은 아니지만, 스프링이 실행되는 시간이 있기때문에 테스트의 양이 많아지는 것을 고려한다면 단위 테스트가 좋은 테스트라 볼 수 있다. 스프링 컨테이너 없이도 실행되는 단위 테스트가 좋은 테스트일 확률이 높음. 반대로, 스프링컨테이너가 있어야 실행되는 테스트코드는 잘못된 테스트코드 설계일 수 있다.

 

스프링 JdbcTemplate

  • 스프링 JdbcTemplate과 Mybatis와 같은 라이브러리는 JDBC API에서 본 반복 코드를 대부분 제거해준다.
  • SQL은 직접 작성해야 한다.
  • 실무에서 아직 많이 사용한다.
rs.close();
pstmt.close();
conn.close();

 

JdbcTemplate을 사용하기 위해서는 Rowmapper를 생성하여 query의 두번째 매개변수로 넣어줘야 한다. 

private RowMapper<Member> memberRowMapper() {
        /*
        return new RowMapper<Member>() {
            @Override
            public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
                Member member = new Member();
                member.setId(rs.getLong("id"));
                member.setName(rs.getString("name"));
                return member;
            }
        }
        위의 코드를 람다로 변경할 수 있다.
        */
        return (rs, rowNum) -> {
            Member member = new Member();
            member.setId(rs.getLong("id"));
            member.setName(rs.getString("name"));
            return member;
        };

    }

 

JPA

  • JPA는 기존의 반복된 코드는 물론이고, 기본적인 SQL을 JPA가 직접 만들어 실행해준다.
  • SQL과 데이터 중심의 설계에서 객체 중심의 설계로 전환할 수 있다.
  • 개발 생산성을 높일 수 있다.

 

build

JPA 사용을 위해 build.gradle에 아래의 의존성을 추가한다.

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

 

 

application.properties 파일 설정

application.properties 파일에 아래의 설정을 추가한다. 

spring.jpa.show-sql=true --JPA가 생성하는 SQL을 출력
spring.jpa.hibernate.ddl-auto=none
--ddl-auto : JPA에서 제공하는 테이블 자동 생성 기능.
--none - 해제, create - 엔티티 정보를 바탕으로 테이블 생성

 

 

public class JpaMemberRepository implements MemberRepository {

    private final EntityManager em;

    public JpaMemberRepository(EntityManager em) {
        this.em = em;
    }
}

JPA를 사용하기 위해서는 EntitiyManager를 주입받아야 한다. 또한, JPQL 문법을 사용해 쿼리를 작성해야 한다.

 

package hello.hellospring.repository;

import hello.hellospring.domain.Member;

import javax.persistence.EntityManager;
import java.util.List;
import java.util.Optional;

public class JpaMemberRepository implements MemberRepository {

    private final EntityManager em;

    public JpaMemberRepository(EntityManager em) {
        this.em = em;
    }

    @Override
    public Member save(Member member) {
        em.persist(member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        Member member = em.find(Member.class, id);
        return Optional.ofNullable(member);
    }

    @Override
    public Optional<Member> findByName(String name) {
        List<Member> result = em.createQuery("select m from Member m where m.name = :name", Member.class)
                .setParameter("name", name)
                .getResultList();
        return result.stream().findAny();
    }

    @Override
    public List<Member> findAll() {
        return em.createQuery("select m from Member m", Member.class).getResultList();
    }
}

JPA에서의 데이터 변경은 모두 트랜잭션 안에서 실행되어야 한다.

 

스프링 데이터 JPA

  • 스프링 데이터 JPA를 사용하면, 리토지토리 구현 클래스 없이 인터페이스 만으로 개발할 수 있다.
  • 설정은 앞의 JPA 설정을 그대로 사용한다.
package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
	// JPARepository를 상속받고있으면 자동으로 구현체를 만들어주고, 스프링 빈에 등록한다.
    @Override
    Optional<Member> findByName(String name);
}

 

SpringConfig

package hello.hellospring;

import hello.hellospring.repository.MemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

    private final MemberRepository memberRepository;

    public SpringConfig(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository);
    }

}

 

한번 JPARepository를 살펴보자.

스프링 데이터 JPA에서는 아래의 기능을 제공한다.

  • 기본적인 CRUD
  • findByName(), findByEmail()과 같은 메서드 이름만으로 조회 기능 제공
  • 페이징 기능 제공
참고로 실무에서 복잡한 동적 쿼리는 Querydsl 라이브러리를 사용한다. 혹은 JPA가 제공하는 네이티브 쿼리를 사용하거나, JdbcTemplate를 사용한다.
profile

숑숑이의 개발일기

@숑숑-

풀스택 개발자 준비중입니다