JPA란? : (Java Persistence API) ORM(Object Relational Mapping)의 기술 표준, 인터페이스의 모음이다. ORM에 대한 자바 API의 규격이며 Hiberate, OpenJAP등이 JPA의 구현체이다. 데이터베이스를 객체지향적으로 관리할 수 있다.
implementation 'org.springframework.boot:spring_boot-starter-data-jpa'
build.gradle에 다음 코드를 추가해주고
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
application.properties에 다음 코드를 써준다. application.properties는 sources 디렉토리 안에 있다.
그 다음으로,
JPA 객체를 매핑해줘야하는데, 그 전에 먼저 클래스와 테이블을 매핑해야한다.
1. @Entity : 클래스를 테이블과 매핑한다고 JPA에게 알려준다. 이 어노테이션이 사용되는 클래스를 엔티티 클래스라고 한다.
2. @Table : 엔티티 클래스에 매핑될 테이블 정보를 알려준다. (name 속성으로 테이블을 설정) 이를 생략하면 클래스이름으로 매핑됨.
3. @Id : 엔티티 클래스의 PK에 매핑한다. 즉, 이 어노테이션이 사용된 필드를 식별자 필드라고 한다.
4. @Column : 필드를 컬럼에 매핑한다. (name 속성을 사용)
5. @Generated Value : 주키의 자동 생성 전력, 즉 인덱스 자동증가 역할을 한다. @Id @GeneratedValue(strategy=GenerationType.AUTO)로 작성하는 경우에!
* show-sql : JPA가 생성하는 SQL을 출력한다.
* ddl-auto : JPA는 테이블을 자동으로 생성하는 기능을 제공 -> create를 사용하면 엔티티 정보를 바탕으로 테이블을 자동 생성해준다 WOW
JPA 엔티티 매핑
: Entity어노테이션이 붙은 클래스의 각 개체와 테이블 간의 연간관계를 형성하는 것을 말한다.
> import javax.persistence.Entity 관련 에러 해결
persistence에서 빨간 줄 에러가 떠서 JPA환경설정이 안되었음을 알고 javax.persistence 관련 환경설정을 다시 해주었다.
먼저 제일 기본적인 build.gradle의 dependencies와 source>application.properties 파일을 다음과 같이 설정해주었다.
1. build.gradle
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
2. 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
이렇게 설정해줬는데도 계속 persistence에서 에러가 뜨길래 구글링구글링. 해답은 jar파일에 있는 것 같았다.
mvnrepository.com/artifact/javax.persistence/javax.persistence-api/2.2
여기서 javax.persistence-api-2.2.jar 파일을 다운로드 받아서 다음과 같이 Project Structure>Modules에 Export 파일에 추가해주었다. (servlet-app.jar은 javax 관련 모듈을 추가해준다고 하여 삽질하다가 추가시킨 파일인데 왜 이 jar 파일로는 해결이 안되었는지 의문. 아마 Persistence 관련 인터페이스가 없었기때문이 아닐까..?)
아무튼 이렇게 했더니 Persistence는 해결이 되었다. 근데 main>hello.hellospring>domain>Member.java에서 import해 준 Entity는 빨간 줄 에러가 뜨는 것을 확인할 수 있었다. 또 다시 멘붕이 와서 이리저리 하다가
다음과 같이 main 패키지 안에서 jar파일을 추가하여 해결할 수 있었다. 아따리 어렵다 ~^^..
암튼 domain>Member.java에서 만들어 준 Memer 클래스를 매핑해주기 위해 클래스 위에 @Entity 어노테이션을 추가해준다.
package hello.hellospring.domain;
import javax.persistence.*;
@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;
}
}
그리고 @Id 어노테이션으로 id필드를 PK로 설정해준다. (id필드는 식별자 필드가 됨)
@GeneratedValue(startegy = GenerationType.IDENTITY) 코드는 테이블에 데이터가 추가될 때마다 PK가 자동 증가하도록 설정하기 위해 작성한다.
이렇게 매핑을 완료하고 repository폴더에 JpaMemberRepository 파일을 생성해 MemberRepsitory 인터페이스의 구현체를 만들자.
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import javax.persistence.*;
import java.util.List;
import java.util.Optional;
public class JpaMemberRepository implements MemberRepository{
private final EntityManager em; //DB와의 통신을 처리. JPA를 쓸려면 Entity Manger을 주입받아야 함.
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 as m", Member.class)
.getResultList();
}
}
EntityManager JPA 기술로 DB와의 통신을 처리하기 위해 필수적으로 주입해야하는 인터페이스이다.
save 메소드에서 em.persist()로 엔티티를 저장하고, Optional<Member> findById(Long id)와 Optional<Member>findByName(String name)을 에서 엔티티를 조회하고 쿼리를 생성한다.
- em.find(데이터 타입, 식별자) 로 엔티티 조회
- em.createQuery(쿼리문, 데이터 타입)으로
- stream() :
- Optional<T> 클래스는 T타입의 객체를 포장해주는 Wrapper 클래스이다. Null Pointer Exception 예외를 회피할 수 있다. Optional <Member>findById는 Member 데이터 타입의 메소드를 형성해주되 null 값이 리턴되면 예외 처리가 이루어진다.
- List<T> 클래스는 T타입의 List를 만들어 관리하는 역할을 한다. List<Member> findAll() 메소드를 형성해주면 return 값에 의해서 Member 엔티티에서 m 칼럼을 가져와 getResultList메서드를 통해 결과를 컬렉션으로 반환한다.
* 컬렉션 인터페이스란, 여러 원소들을 담을 수 있는 자료구조를 뜻한다.
> 자바의 자료구조 유형은 어떤게 있나요?
- 순서가 있는 목록인 List형
- 순서가 중요하지 않은 목록인 Set형
- 먼저 들어온 것이 먼저 나가는 Queue형
- KEY-VALUE의 형태로 저장되는 Map형
출처: https://www.crocus.co.kr/1553 [Crocus]
여기까지가 JpaMemberRepository에 대한 설명이다.
스프링 데이터 JPA
- 인터페이스를 통한 기본적인 CRUD 구현
- 페이징 기능 제공
+ 동적 쿼리 Querydsl 라이브러리 사용해서 쿼리도 자바 코드로 안전하게 작성할 수 있다.
'Framework > Spring' 카테고리의 다른 글
스프링 관련 의문점 다루기 (0) | 2021.02.06 |
---|---|
스프링 복습 및 기초 다지기 (0) | 2021.02.05 |
인프런 스프링 입문 강의 #백엔드 개발 (0) | 2021.01.30 |
인프런 스프링 입문 강의 #데이터베이스 (0) | 2021.01.29 |
인프런 스프링 입문 강의 #웹 MVC 개발 (0) | 2021.01.28 |