스프링 데이터 - 2 (스프링 부트 활용 - 8)
1. ORM, JPA, 스프링 데이터 JPA 개요
- ORM (Object - Reltional - Mapping) 와 JPA (Java Persistence API)
객체와 릴레이션을 맵핑(ORM)할 때 발생하는 개념적 불일치를 해결하는 프레임워크(JPA)
- 스프링 데이터 JPA
JPA 표준 스펙을 아주 쉽게 사용할 수 있게 스프링 데이터로 추상화 시켜 놓은 것
Spring Data JPA -> JPA -> Hibernate -> DataSource
2. Spring-Data-JPA 연동
1) JPA, PostgreSql 의존성 추가
1-1) 프로퍼티에 디비 연결 설정
2) @Entity 클래스 만들기
getter, setter, equals, hashCode 오버라이드
@Id : 아이디로 사용
@GeneratedValue : 자동으로 값이 만들어지게 설정
@Entity
public class Account {
@Id @GeneratedValue
private Long id;
private String username;
private String password;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Account account = (Account) o;
return Objects.equals(id, account.id) &&
Objects.equals(username, account.username) &&
Objects.equals(password, account.password);
}
@Override
public int hashCode() {
return Objects.hash(id, username, password);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3) Repository 인터페이스 만들기
실제 구현체를 만들고 빈으로 만드는 것은 스프링 JPA가 알아서 해줌
따라서, JDBC를 쓰는 경우는 거의 없고 JPA를 주로 사용함
쿼리를 사용해야 하는 경우에도 JPA에서 사용 가능 (@Query)
예) @Query(nativeQuery = true, value = "select * from account where username = '{0}'")
public interface AccountRepository extends JpaRepository<Account, Long> {
Account findByUsername(String username);
// 반드시 있어야 하는 경우라면 그냥 엔티티 타입을 리턴받고 없는 경우에 예외를 던집니다.
// 그런데 있을 수도 있고 없을 수도 있는 경우에 대한 메소드라면 Optional로 받아옵니다.
}
4) 테스트 만들기
- H2 DB를 테스트 의존성에 추가하기
- @DataJpaTest (슬라이스 테스트) 작성
Repostitory와 관련된 빈들만 등록해서 테스트
통합 테스트를 한다면 느리고, 테스트용 DB가 필요하다. (그렇게 하지 않으면 테스트 코드로 인해 디비 변경될 수 있음)
따라서 슬라이싱 테스트(인 메모리 데이터베이스로 테스트)를 권장
@RunWith(SpringRunner.class)
@DataJpaTest()
public class AccountRepositoryTest {
@Autowired
DataSource dataSource;
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
AccountRepository accountRepository;
@Test
public void di() throws SQLException {
Account account = new Account();
account.setUsername("hongchan");
account.setPassword("pass");
Account newAccount = accountRepository.save(account);
assertThat(newAccount).isNotNull();
Account existingAccount = accountRepository.findByUsername(newAccount.getUsername());
assertThat(existingAccount).isNotNull();
Account nonExistingAccount = accountRepository.findByUsername("jiyun");
assertThat(nonExistingAccount).isNull();
}
}
3. 데이터베이스 초기화
- JPA를 사용한 데이터베이스 초기화
create, create-drop, update
주로 update를 사용함(변경된 스키마를 자동으로 생성), create-drop은 데이터가 지워지기 때문
운영 DB의 경우 vaildate를 사용하고, false를 줌 (훨씬 안정적인 옵션임)
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
- SQL 스크립트를 사용한 데이터베이스 초기화
schema.sql, data.sql 을 리소스 디렉토리에 두면 해당 sql문이 순서대로 실행됨
처음에 개발할 때는 update 사용
나중에 어느정도 베포할 때 쯤 되면, create로 두고 테스트 코드에서 깔끔한 스키마를 생성하도록 한 다음에,
이를 복사해서 schema.sql로 사용
update를 계속 쓰면 스키마가 굉장히 지저분해짐
ex) update로 두고 email -> emailAddr 로 컬럼을 변경하면, 컬럼을 추가할 뿐, 기존 컬럼은 남아있음
4. 데이터베이스 마이그레이션 툴
스키마 변경, 데이터 변경을 버전 관리처럼 관리할 수 있음
1) flyway 의존성 추가
2) 마이그레이션 디렉토리 및 파일 추가
디렉토리 경로 : db/migration
파일 이름 : V숫자__이름.sql
인프런 백기선님 '스프링 부트’ 강의를 듣고 정리한 내용입니다.