지금까지는 메모리 레포지토리를 사용해서 데이터를 저장했지만, 그렇게 하면 서버를 내리면 데이터가 없어진다. 그렇기에 실무에서는 데이터베이스를 사용한다.
실무에서는 MySQL을 많이 사용하지만 개발이나 테스트 용도로 가볍고 편리한 DB인 H2
https://www.h2database.com/html/main.html
download를 받은 후 다 설치를 완료하면
H2 Console을 실행시켜준다.
url에서 localhost부분이 ip로 되어있을텐데 가끔 오류가 발생할 땐 localhost로 바꿔서 (나머지 뒤에 부분은 수정X) 해주면 된다.
create table member
(
id bigint generated by default as identity,
name varchar(255),
primary key (id)
);
H2 데이터베이스에 접근해서 member 테이블 생성해준다.
SELECT * FROM MEMBER;
SELECT도 가능
김영한님 : "
이렇게 JDBC API로 직접 코딩하는 것은 20년 전 이야기이다. 따라서 고대 개발자들이 이렇게 고생하고 살았구나 생각하고, 정신건강을 위해 참고만 하고 넘어가자."
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'com.h2database:h2'
build.gradle 파일에 jdbc, h2 데이터베이스 관련 라이브러리 추가
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
resources > application.properties 스프링 부트 데이터베이스 연결 설정 추가
순수 Jdbc 와 JdbcTemplate의 구현은 강의를 참고 !
- JPA는 기존의 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행해준다.
- JPA를 사용하면, SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환 가능
- JPA를 사용하면 개발 생산성을 크게 높인다.
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
build.gradle 파일에 JPA 관련 라이브러리 추가
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
resources > application.properties 스프링 부트에 JPA 설정 추가
show-sql
: JPA가 생성하는 SQL을 출력한다.
ddl-auto
: JPA는 테이블을 자동으로 생성하는 기능을 제공하는데 none 를 사용하면 해당 기능을 끈다.
public class JpaRepository implements MemberRepository {
private final EntityManager em;
public JpaRepository(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();
}
}
repository > JpaRepository
Jpa는 EntityManager로 모든걸 동작한다. build.gradle에서 라이브러리를 받았으면 스프링 부트가 자동으로 데이터베이스 정보를 기반으로 연결해서 EntityManager를 만들어준다. 이제 그 EntityManager를 인젝션받으면 된다.
import org.springframework.transaction.annotation.Transactional;
@Transactional
public class MemberService {
...
}
스프링은 해당 클래스의 메서드를 실행할 때 트랜잭션을 시작하고, 메서드가 정상 종료되면 트랜잭션을 커밋한다. 만약 런타임 예외가 발생하면 롤백한다.
JPA를 통한 모든 데이터 변경은 트랜잭션 안에서 실행해야 한다!
@Configuration
public class SpringConfig {
private final DataSource dataSource;
private final EntityManager em;
public SpringConfig(DataSource dataSource, EntityManager em) {
this.dataSource = dataSource;
this.em = em;
}
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
// return new MemoryMemberRepository();
// return new JdbcMemberRepository(dataSource);
// return new JdbcTemplateMemberRepository(dataSource);
return new JpaRepository(em);
}
}
SpringConfing.java
스프링 부트와 JPA만 사용해도 개발 생산성이 정말 많이 증가하고, 개발해야할 코드도 확연히 줄어든다. 여기에 스프링 데이터 JPA를 사용하면, 기존의 한계를 넘어 마치 마법처럼, 피로지토리에 구현 클래스 없이 인터페이스 만으로 개발을 완료할 수 있다. 그리고 반복 개발해온 기본 CRUD 기능도 스프링 데이터 JPA가 모두 제공한다.
스프링 부트와 JPA라는 기반 위에, 스프링 데이터 JPA라는 프레임워크를 더하면 개발 효율 ↑
주의: 스프링 데이터 JPA는 JPA를 편리하게 사용하도록 도와주는 기술이다. 따라서 JPA에 대한 충분한 이해를 가지고 스프링 데이터 JPA를 학습해야 한다.
public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
Optional<Member> findByName(String name);
}
repository > SpringDataJpaMemberRepository
@Configuration
public class SpringConfig {
private final MemberRepository memberRepository;
@Autowired
public SpringConfig(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Bean
public MemberService memberService() {
return new MemberService(memberRepository);
}
}
SpringConfing.java
스프링 데이터 JPA가 SpringDataJpaMemberRepository 를 스프링 빈으로 자동 등록해준다.
- 인터페이스를 통한 기본적인 CRUD
- findByName() , findByEmail() 처럼 메서드 이름 만으로 조회 기능 제공
- 페이징 기능 자동 제공
더 자세한 내용은 공식문서로 Spring Data JPA - Reference Documentation
실무에서는 JPA와 스프링 데이터 JPA를 기본으로 사용하고, 복잡한 동적 쿼리는 Querydsl이라는 라이브러리를 사용하면 된다. Querydsl을 사용하면 쿼리도 자바 코드로 안전하게 작성할 수 있고, 동적쿼리도 편리하게 작성할 수 있다. 이 조합으로 해결하기 어려운 쿼리는 JPA가 제공하는 네이티브 쿼리를 사용하거나, Jdbc Template로 해결하면 된다.
⭐⭐⭐ 인프런에서 진행한 김영한님의 강의(스프링 입문)를 토대로 정리한 포스팅입니다. 자세한 내용은 링크를 참고하시기 바랍니다. ⭐⭐⭐