📹 참고 : 인프런 [ 스프링 입문 - 김영한 ]
JPA(Java Persistence API)는 자바 표준 ORM(Object-Relational Mapping) 기술.
ORM은 객체(Object)와 관계형 데이터베이스(Relational Database) 간의 매핑을 자동화하여 객체 지향 프로그래밍 언어에서 관계형 데이터베이스를 사용할 수 있도록 지원.
-JPA는 객체와 관계형 데이터베이스 간의 매핑 정보를 어노테이션(annotation)을 통해 지정하고, 이를 바탕으로 자바 객체와 데이터베이스 테이블 간의 변환 작업을 자동화 함.
JPA는 기존의 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행해준다.
JPA를 사용하면, SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환을 할 수 있다.
JPA를 사용하면 개발 생산성을 크게 높일 수 있다.
JPA 주요 개념과 기능
Entity 클래스: JPA에서 관리되는 객체를 나타내는 클래스입니다. 각 Entity 클래스는 테이블에 매핑되며, 데이터베이스의 행(row)을 나타냅니다.EntityManager: JPA의 핵심 인터페이스 중 하나로, Entity의 생명주기를 관리하고, 데이터베이스와의 통신을 담당합니다. EntityManager를 사용하여 데이터베이스로부터 Entity를 조회하거나 새로운 Entity를 생성하고, 수정, 삭제할 수 있습니다.Entity 매핑: JPA에서는 객체와 테이블 간의 매핑 정보를 어노테이션을 통해 지정합니다. 예를 들어, @Entity, @Table, @Column, @Id 등의 어노테이션을 사용하여 Entity 클래스와 테이블, 컬럼 간의 매핑을 지정할 수 있습니다.CRUD 작업: JPA는 데이터베이스와의 CRUD(Create, Read, Update, Delete) 작업을 지원합니다. EntityManager를 사용하여 Entity를 데이터베이스에 저장하거나 조회, 수정, 삭제할 수 있습니다.JPQL(Java Persistence Query Language): JPA는 객체 지향적인 쿼리 언어인 JPQL을 제공합니다. JPQL은 엔티티 객체를 대상으로 하는 쿼리를 작성할 수 있으며, SQL과 유사하지만 데이터베이스 테이블이 아닌 엔티티 객체를 대상으로 쿼리를 실행합니다.
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'
//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는 제거해도 된다.
스프링 부트에 JPA 설정 추가
resources/application.properties
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 를 사용하면 엔티티 정보를 바탕으로 테이블도 직접 생성해준다.JPA 엔티티 매핑
java/hello/hellospring/domain/Member.java
@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;
}
}
@Entity : JPA 엔터티 클래스@Id : Primary Key를 나타내는 필드@GeneratedValue(strategy = GenerationType.IDENTITY) : 자동 생성되는 값(strategy = GenerationType.IDENTITY는 데이터베이스에서 자동 증가하는 열을 사용)JPA 회원 리포지토리
java/hello/hellospring/repository/JpaMemberRepository.java
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); // 주어진 ID로 멤버를 조회
return Optional.ofNullable(member); // 조회된 멤버를 Optional로 감싸서 반환
}
@Override
public Optional<Member> findByName(String name) {
// 이름을 사용하여 멤버를 조회하는 JPQL 쿼리 실행
List<Member> result = em.createQuery("select m from Member m where m.name = :name", Member.class)
.setParameter("name", name)// 이름 매개변수 설정
.getResultList(); // 결과 리스트 반환
return result.stream().findAny(); // 조회된 결과 중 임의의 결과를 Optional로 감싸서 반환
}
@Override
public List<Member> findAll() {
// 모든 멤버를 조회하는 JPQL 쿼리 실행
return em.createQuery("select m from Member as m", Member.class).getResultList();
// 결과 리스트 반환
}
}
Entity Mannager Method
find(): 데이터베이스에서 특정 엔티티를 조회하는 데 사용됨.
- 매개변수: 조회할 엔티티의 클래스 타입과 해당 엔티티의 기본 키(primary key) 값을 전달.
- 반환값: 주어진 기본 키 값에 해당하는 엔티티 객체를 반환. 만약 해당하는 엔티티가 존재하지 않는다면 null을 반환.createQuery(): JPQL 쿼리를 생성하는 데 사용. JPQL은 객체 지향적인 쿼리 언어로, 엔티티를 대상으로 쿼리를 작성.
- 매개변수: JPQL 쿼리 문자열과 반환할 결과의 타입을 지정하는 클래스 타입을 전달. 필요한 경우 쿼리에 파라미터를 전달 ex) :name.
- 반환값: 지정된 JPQL 쿼리에 따라 실행된 결과를 반환. 이는 일반적으로 엔티티의 리스트나 엔티티 하나일 수 있음.persist(): 엔티티를 영속 상태로 만들어 데이터베이스에 저장하는 데 사용. 영속 상태란 엔티티가 영구적으로 저장되어 데이터베이스의 관리를 받는 상태를 의미합.
- 매개변수: 저장할 엔티티 객체를 전달.
- 반환값: 반환값이 없으며, 엔티티를 영속 상태로 만들어 데이터베이스에 저장.
서비스 계층에 트랜잭션 추가
java/hello/hellospring/service/MemberService.java
import org.springframework.transaction.annotation.Transactional
@Transactional
public class MemberService {}
JPA를 사용하도록 스프링 설정 변경
@Configuration
public class SpringConfig {
private EntityManager em;
@Autowired
public SpringConfig(EntityManager em) {
this.em = em;
}
/* jdbcTemplate
private final DataSource dataSource;
public SpringConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
*/
@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);
}
}
테스트
/test/java/hello/hellospring/service/MemberServiceIntegrationTest.java
이전에 만들어 놓은 통합테스트의 회원가입을 실행해보자.
결과를 디비에서 확인하기 위해 회원가입 메소드에 @Commit 어노테이션을 붙여 실행해보자.


hello 라는 회원 이름이 저장된 것을 확인하였다.