6/30 스프링 DB 접근 기술 (2) - JPA
JPA
JPA ORM : Object Relational databse Mapping
객체와 relational 데이터베이스 테이블을 매핑한다
SQL 쿼리도 JPA가 자동으로 형성해준다
build.gradle에서
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
추가해주고,
applocation.properties에서
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
jpa가 날리는 쿼리 확인 가능
jpa는 자동으로 테이블 생성해주나, 이번 실습에선 이미 member테이블이 만들어져있는 상태이므로
자동으로 테이블 생성해주는 기능은 끈다.
jpa는 인터페이스만 제공되는 것이고 그 구현체로hibernate가 있다.
매핑은 어떻게?
@Entitiy : JPA가 관리하는 entity가 됨
@ID : pk 매핑
@GeneratedValue(strategy = GenerationType.IDENTITY)
db가 알아서 생성해줌 - identity 전략
JPA는 entity manager로 모든게 동작을 한다
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
요 부분에서 스프링부트가 자동으로 entity manager를 생성해준다
따라서 만들어진 entitiy manager를 injection 받으면 된다.
private final EntityManager em;
public JpaMemberRepository(EntityManager em){
this.em = em;
}
@Override
public Member save(Member member) {
em.persist(member); // persist : 영구적으로 저장한다 보면 됨
return member;
}
->JPA가 id까지 member에 setId까지 다해준다.
@Override
public List<Member> findAll() {
List<Member> result = em.createQuery("select m from Member m", Member.class).getResultList();
return result;
}
}
inline 단축키 : shift + option + enter
@Override
public List<Member> findAll() {
return em.createQuery("select m from Member m", Member.class).getResultList();
}
요렇게 합쳐짐
@Override
public Member save(Member member) {
em.persist(member); // persist : 영구적으로 저장한다 보면 됨
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();
}
pk기반이 아닌 findByName, findAll의 경우에는 쿼리를 작성해주어야 한다.
JPA를 쓸려면 항상 transaction이 있어야 한다.
서비스 계층에 @Transactional 해준다. 데이터를 저장하거나 변경할 땐 transaction이 있어야 한다.
모든 데이터 변경이 transaction 안에서 실행이 되어야한다.
@Transactional
public class MemberService {
스프링 설정 변경
@Configuration
public class SpringConfig {
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);
}
}
스프링 데이터 JPA
리포지토리에구현클래스없이 인터페이스만으로 개발 완료 가능.
반복 개발해온 기본 CRUD 기능도 스프링데이터 JPA가 모두 제공한다.
public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
Optional<Member> findByName(String name);
}
인터페이스가 인터페이스를 받을 때에는 extends, 인터페이스는 다중상속이 가능
JpaRepository를 상속받고 있으면 스프링 데이터 JPA가 구현체를 만들어서 스프링 빈에 등록해준다
@Configuration
public class SpringConfig {
private final MemberRepository memberRepository;
@Autowired
public SpringConfig(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Bean
public MemberService memberService() {
return new MemberService(memberRepository);
}
}
스프링 설정 수정
스프링데이터 JPA 제공기능 인터페이스를통한기본적인 CRUD
findByName(), findByEmail() 처럼 메서드 이름 만으로 조회 기능 제공, 페이징 기능 자동 제공