build.gradle
// 추가
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
application.properties
// 추가
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
Member.java
package hello.hellospring.domain;
import javax.persistence.*;
@Entity
public class Member {
// IDENTITY : db 가 id 를 자동 생성해주는 것
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// db 에 있는 column 이름과 mapping 가능
// @Column(name = "username")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
JpaMemberRepository.java
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{
private final EntityManager em;
// injection 받음
public JpaMemberRepository(EntityManager em){
this.em = em;
}
@Override
public Member save(Member member) {
// insert query 와 setId 까지 전부 실행
em.persist(member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
Member member = em.find(Member.class, id);
return Optional.ofNullable(member);
}
// pk 기반이 아니면 jpql 을 사용
@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() {
// 객체지향 sql 사용 (jpql) -> 객체(entity) 를 대상으로 query 를 보냄
return em.createQuery("select m from Member m", Member.class).getResultList();
}
}
MemberService.java 상단에 추가
SpringDataJpaMemberRepository interface
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
// JpaRepository 가 구현체 생성하여 자동으로 bean 에 등록해줌
public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
// Interface 로 편리하게 JPQL 구현
Optional<Member> findByName(String name);
}
Spring Config
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;
@Configuration
public class SpringConfig {
private final MemberRepository memberRepository;
@Autowired
public SpringConfig(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Bean
public MemberService memberService(){
return new MemberService(memberRepository);
}
}
Spring Data JPA 제공 기능
실무에서는 Spring Data JPA 와 JPA 를 기본적으로 사용하고, 복잡한 동작 쿼리는 Querydsl 이라는 라이브러리를 사용함 → Querydsl 은 쿼리도 자바코드로 안전하게 작성이 가능하고 동적 쿼리도 편리하게 작성 가능
앞서 말한 조합으로 해결하기 어려운 쿼리는 JPA 가 제공하는 네이티브 쿼리를 사용하거나 Jdbc Template 를 사용하면 됨