H2 데이터베이스 설치
아래의 링크에서 1.4.200 버전을 설치한다.
만일 이미 설치후 실행까지 했다면 ~/test.mv.db 파일을 꼭 삭제 해야한다.
https://www.h2database.com/html/download-archive.html
맥 사용자의 경우 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를 사용한다.
'Backend > Spring' 카테고리의 다른 글
[Spring] 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 #1 웹 애플리케이션 이해 (0) | 2024.06.17 |
---|---|
[Spring] 스프링 입문 - 코드로 배우는 스프링 부트 #7 AOP (0) | 2024.06.16 |
[Spring] Spring MVC란? Spring MVC에서 HTTP요청이 들어왔을 때의 흐름은? (0) | 2024.01.04 |
[Spring] Spring AOP란? Spring AOP는 CTW, PCW, LTW, RTW 중에 무엇일까? (1) | 2024.01.03 |
[Spring] 리플렉션(Reflaction)이란? 생성자 주입은 빈 생성때의 리플렉션 외에 추가적인 리플렉션을 진행하는가? (0) | 2024.01.02 |