확장에는 열려있고 수정, 변경에는 닫혀있다.
스프링의 DI를 사용하면 기존 코드를 수정하지 않고 설정만으로 구현 클래스를 변경할 수 있다.
DataSource는 데이터베이스 커넥션을 획득할 때 사용하는 객체다. 스프링 부트는 데이터베이스 커넥션 정보를 바탕으로 DataSource를 생성하고 스프링 빈으로 만들어준다. 그래서 DI를 받을 수 있다.
스프링 컨테이너와 테스트를 함께 실행한다.
테스트 시작 전 트랜잭션을 시작하고 테스트 완료 후 언제나 데이터를 롤백한다. DB에 데이터를 남기지 않아서 다음 테스트에 영향을 주지 않는다.
순수 자바 코드로 단위별로 테스트 하는 방식이다.
디비와 연동하여 테스트 하는 방식이다.
반복 코드를 제거해 주는 라이브러리이다.
스프링 JdbcTemplate과 MyBatis 같은 라이브러리는 JDBC API에서 본 반복 코드를 대부분 제거해준다. 하지만 SQL은 직접 작성해야 한다.
스프링 빈으로 등록되었을 때 생성자가 단 한 개만 존재하면 @Autowired 어노테이션을 생략할 수 있다.
Jdbc Template를 통해서 query를 날리고 RowMapper를 통해서 매핑을 한다.
기존의 반복 코드와 기본적인 SQL도 JPA가 만들어서 실행해준다.
SQL과 데이터 중심 설계에서 객체 중심의 설계로 패러다임을 전환할 수 있다.
인터페이스: JPA 자바 진영의 표준 인터페이스
구현체: 하이버네이트
@GeneratedValue(strategy=GenerationType.INDENTITY): 데이터베이스가 자동으로 id 번호를 매핑해주는 전략
@Id//primary key
@GeneratedValue(strategy = GenerationType.IDENTITY)
pirvate Long id;
build.gradle에 jpa-data를 참조하면 스프링 부트가 자동으로 데이터베이스와 연결해서 EntityManager를 생성한다. 따라서 이를 주입받으면 된다.
private final EntityManager em;
public JpaMemberRepositoty(EntityManager em){
this.em=em;
}
Insert과정: EntityManager가 insert 쿼리를 다 만들어서 데이터베이스에 집어넣고 id값까지 세팅한다.
@Override
public Member save(Member member){
em.persist(member);
return member;
}
@Override
public Optional<Member> findById(Long id){
em.find(Member.class,id)//조회할 타입, pk값인 id
return Optional.ofNullable(member);
}
jpql query: 테이블 대상으로 쿼리를 날리는게 아니라 객체를 대상으로 쿼리를 날린다. 아래는 Member entity를 대상으로 쿼리를 날린다. Member entity 객체 자체를 조회한다.
@Override
public List<Member> findAll(){
return em.createQuery("select m from Member m",Member.class)
.getResultList();
}
저장, 조회, 삭제 등은 sql을 짤 필요가 없다. 하지만 pk(primary key) 기반이 아닌 나머지 기능들은 jpql을 작성해야 한다.
JPA를 스프링에서 감싸서 제공하는 기술이 Spring Data JPA이다. Spring Data JPA를 사용하면 jpql 쿼리를 작성하지 않아도 된다.
JPA를 사용하기 위해선 항상 Transaction이 필요하다. MemberService에 @Transactional 어노테이션을 붙여준다. 데이터를 저장하거나 수정할 때 Transaction이 필요하다. JPA는 join이 들어올 때 모두 Transaction 안에서 수행되어야 한다.
@Transactional
public class MemberService{
...
}
@Commit을 사용하면 실제 데이터베이스에 반영됨
@Test
@Commit
void 회원가입() {
...
}
스프링 데이터 JPA는 JPA를 편리하게 사용할 수 있도록 도와주는 기술이다. 인터페이스만으로 개발을 완료할 수 있다.
SpringDataJpaMemberRepository가 JpaRespository를 받고 있으면 구현체를 자동으로 만들어준다. 그래서 SpringDataJpaMemberRepository가 스프링 빈에 자동으로 등록된다. 스프링 데이터 JPA가 SpringDataJpaMemberRepository를 보고 구현체를 자동으로 등록해준다. 그래서 그걸 가져다 쓰면 된다.
public interface SpringDataJpaMemberRepository extends JpaRepository<Member,Long>,MemberRepository {//인터페이스가 인터페이스를 받는 경우 extends
@Override
Optional<Member> findByName(String name);
}
스프링 데이터 JPA가 만들어둔 빈이 자동으로 등록된다.
public class SpringConfig {
private final MemberRepository memberRepository;
public SpringConfig(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
}