반응형
저번에는 JDBCTemplate이라는 것을 이용해서 기존 JDBC의 코드를 간결하게 만들었습니다. 그러나 SQL은 직접 작성했어야 했었습니다. 이제 JPA라는 것을 이용해 SQL도 자동으로 만들어지는 부분에 대해서 알아보겠습니다.
JPA를 적용해보자
일단 JPA에 대해 간단히 요약하자면 아래와 같습니다.
- JPA는 기존의 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행해줍니다.
-
JPA를 사용하면, SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환을 할 수 있습니다.
-
JPA를 사용하면 개발 생산성을 크게 높일 수 있습니다.
1. build.gradle 파일에 JPA, h2 데이터베이스 관련 라이브러리를 추가합니다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation ('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
developmentOnly("org.springframework.boot:spring-boot-devtools")
// implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
}
spring-boot-starter-data-jpa는 내부에 jdbc 관련 라이브러리를 포함하기 때문에 jdbc는 제거합니다.
2. application.properties에 스프링 부트 JPA 설정을 추가합니다.
spring.devtools.restart.enabled=true
spring.devtools.restart.poll-interval=2s
spring.devtools.restart.quiet-period=1s
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
-
show-sql = JPA가 생성하는 SQL을 볼 수 있습니다,
-
ddl-auto = JPA는 자동으로 테이블을 생성하는 기능이 있는데, none으로 설정하면 자동으로 생성하지 않습니다. create라고 설정하면 테이블 엔티티정보들을 바탕으로 자동으로 테이블을 생성합니다.
3. 설정을 다 했으면, JPA의 엔티티를 Member클래스에서 매핑해줍니다.
package hello.hellospring.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Member {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4. 엔티티 매핑 후, repository 경로에 JpaMemberRepository 클래스를 생성하고 아래와 같이 작성합니다.
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 {
// JPA는 EntityManager라는 것을 바탕으로 동작한다.
// build.gradle에 추가한 data-jpa 라이브러리 때문에, 스프링부트가 자동으로 EntityManager라는 것을 현재 데이터베이스와 연결해서 자동으로 생성해준다.
private final EntityManager em;
public JpaMemberRepository(EntityManager em) {
this.em = em;
}
@Override
public Member save(Member member) {
em.persist(member); // .persist() = 영구 저장한다는 의미.
return member;
// 이렇게만 하면 자동으로 id까지 세팅해서 자동으로 insert SQL을 생성 후 데이터를 저장한다.
}
@Override
public Optional<Member> findById(Long id) {
Member member = em.find(Member.class, id);
// .find(a,b) = a는 조회할 값의 타입, b는 식별자.
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();
}
}
5. MemberService에 어노테이션 하나를 추가해 줍니다.
import org.springframework.transaction.annotation.Transactional;
@Transactional // JPA를 사용할 때는 항상 트랜잭션이 있어야 한다. 회원가입에만 쓰이지만 일단 클래스에 추가했다.
public class MemberService {
- 스프링은 해당 클래스의 메서드를 실행할 때 트랜잭션을 시작하고, 메서드가 정상 종료되면 트랜잭션을 커밋하고, 만약 런타임 예외가 발생하면 롤백합니다.
-
JPA를 통한 모든 데이터 변경은 트랜잭션 안에서 실행해야 한다.
6. JPA를 사용하도록 스프링 설정을 변경합니다.
package hello.hellospring;
import hello.hellospring.repository.*;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
@Configuration // -> 스프링이 뜰 때, 이 어노테이션을 읽고 스프링 빈을 만들라는 것이구나! 라고 인식을 하고 아래 작성한 빈들을 등록한다.
public class SpringConfig {
// private DataSource dataSource;
//
// @Autowired
// public SpringConfig(DataSource dataSource) {
// this.dataSource = dataSource;
// }
private EntityManager em;
@Autowired
public SpringConfig(EntityManager em) {
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 JpaMemberRepository(em);
}
}
반응형
'dev-ing > spring' 카테고리의 다른 글
[Springboot] 스프링부트 기초 (16) AOP란? AOP 적용하기 공통 관심사항 핵심 관심사항 (0) | 2022.11.02 |
---|---|
[Springboot] 스프링부트 기초 (15) JPA 스프링 데이터 JPA란? 스프링 데이터 JPA 적용하기 (0) | 2022.11.01 |
[Springboot] 스프링부트 기초 (13) JDBC 스프링 컨테이너와 DB연동해서 통합테스트 하기 JDBC Template (0) | 2022.10.27 |
[Springboot] 스프링부트 기초 (12) JDBC로 H2 데이터베이스와 연동하기 (0) | 2022.10.26 |
[Springboot] 스프링부트 기초 (11) H2 데이터베이스 설치하기 (0) | 2022.10.25 |
댓글