Jpa(java persistence api)
장점 : 기존의 반복 코드를 줄임과 동시에 sql 쿼리도 jpa가 직접 실행해준다.
객체를 jpa에 넣으면 db와 관련된 작업 수행
-> sql과 데이터 중심 설계에서실제 객체 중심으로 패러다임 전환가능
-> 개발 생산성 업
-> 마이바티스와 비교했을 때, jpa가 압도적 사용량
스프링 프레임워크 = 거대 프레임 워크인데
jpa도 스프링만큼 거대하고 깊이있다.
- build.gradle 파일 수정
1. spring-boot-starter-data-jpa 작성
이는 내부에 jdbc 관련 라이브러리를 포함한다. 따라서 기존에 있던 jdbc는 제거해도됨.
2. gradle refresh해준다
- application.properties 수정
1. spring.jpa.show-sql=true를 적어준다.
JPA가 생성하는 SQL을 출력해주어 직접 볼 수 있다.
2. spring.jpa.hibernate.ddl-auto=none 추가
JPA는 테이블을 자동으로 생성하는 기능을 제공하는데 none 를 사용하면 해당 기능을 끈다. 우리는 이미 테이블을 만들어놓았기 때문!
none 대신 create 를 사용하면 엔티티 정보를 바탕으로 테이블도 직접 생성해준다고 한다.
JPA 적용해보기
우선 라이브러리에 jpa(인터페이스)와 hibernate(구현체)가 들어왔는지 확인 후 진행한다.
jpa는 ORM(object-relational database table-mapping) 기술이다. (R은 Rdbms할 떄 R과 동일)
mapping은 어떻게 할까? 멤버 도메인에 @Entity 작성
@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;
}
}
->이제부터 이것은 jpa가 관리하는 entity이다!!
그리고 pk도 매핑해줘야하는데, 원하는 변수 위에@Id 어노테이션을 작성하면 된다.
그렇게 되면 왼쪽에 열쇠 모양 아이콘이 있는 걸 확인할 수 있다.
pk 설정 완료
데이터 베이스에 insert할 때, id를 넣지 않아도 알아서 db가 id값을 1씩 증가하면서 값을 넣어주는 방식이 있는데 이를, Identity strategy 라고 한다.
1씩 증가되길 원하는 변수에 @GeneratedValue(strategy = GenerationType.IDENTITY) 해주자.
만약, 객체의 어트리뷰트와 테이블의 열이름이 다른경우
해당 변수 위에 @Column(name = "테이블열이름") 해주면 된다.
@Column(name = "username") // 테이블에서 name에 해당 하는 열 이름이 username인 경우
private String name; // 두가지 요구사항
위의 어노테이션들을 가지고 jpa가 db와 매핑해준다!!!
리포지토리 클래스에는 EntityManager 변수를 하나 선언하는데, 아까 가져온 라이브러리(data-jpa)들을 보고 spring boot가 자동으로 현재 db와 연결까지 다 해서 EntityManager를 만들어 준다.
사용자는 그것을 생성자에 주입 받으면 된다!
-> jpa쓰려면 EntityManager를 Injection 받아야한다.
public class JpaMemberRepository implements MemberRepository{
private final EntityManager em;
public JpaMemberRepository(EntityManager em) { // injection
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();
}
}
저장할 때는 em의 persist를 이용하면 끝!
이렇게만 하면 jpa가 Insert 쿼리 만들어서 데이터베이스에 다 넣어버리고 member 객체에 setid까지 다 해준다.
find는 파라미터에 조회할 타입이랑 식별자(pk)넣어주면 끝(Member.class, id)
- 항상 타입을 적어주자 ex) Member.class
pk가 아닌 걸로 찾거나, 여러 개를 찾아서 리스트를 돌릴 때는(ex. findAll())
- jpql 사용
보통의 sql처럼 테이블 대상으로 쿼리를 날리는 것이 아닌, 객체를 대상으로 한다. 그럼 그것이 sql로 번역이 된다.
select m from Member m where m.name = :name을 보면, Member 타입의 객체 중, name이 find하고자 하는 name과 같은 것을 찾아 그 객체를 반환해준다. 그래서 findAll() 같은 경우에 기존 sql보다 더 유리하다.
jpa를 쓰려면 항상 trasaction이 있어야 한다.
Service로 넘어가서 @Transactional 작성해주자.}
import org.springframework.transaction.annotation.Transactional
@Transactional
public class MemberService {}
스프링은 해당 서비스의 메서드를 실행할 때 트랜잭션을 시작하고, 메서드가 정상 종료되면 트랜잭션을 커밋한다. 만약 런타임 예외가 발생하면 롤백한다.
JPA를 통한 모든 데이터 변경은 트랜잭션 안에서 실행해야 한다.
config파일 수정
1. 리포지토리의 return 값 수정해주자
2. 생성자를 entitymanager가 인젝션 되도록 수정한다.
@Configuration
public class SpringConfig {
@PersistenceContext
private final EntityManager em;
public SpringConfig(EntityManager em) {
this.em = em;
}
@Bean
public MemberService memberService(){
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
//return new JdbcTemplateMemberRepository(dataSource);
return new JpaMemberRepository(em);
}
}
다음 시간엔 spring data jpa 기술에 대해 알아보자!
'스프링(JAVA)' 카테고리의 다른 글
스프링 DB 접근 기술 #3 spring data jpa (0) | 2022.09.25 |
---|---|
스프링 DB 접근 기술 #1 JDBC, JDBC Template (0) | 2022.09.25 |
Spring 웹mvc 간단 회원 관리 예제(홈 화면, 등록, 조회) (0) | 2022.09.25 |
Spring 스프링 빈과 의존관계 (0) | 2022.09.25 |
Spring 회원 관리 예제 - 테스트 코드 (0) | 2022.09.25 |