728x90
6.스프링DB접근기술
목차
- 2.스프링 통합테스트
- 3.스프링 JdbcTemplate
- 4.JPA
- 5.스프링 데이터 JPA
2.스프링 통합테스트
MemberServiceIntegrationTest 테스트추가!
@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {
@Autowired MemberService memberService;
@Autowired MemberRepository memberRepository;
//...
}
- 기존 MembeerServiceTest 에서 @SpringBootTest @Transactional를 추가한다
- @Transactional을 추가하면 트랜잭션 롤백을한다
- DB트랜잭션 롤백을 하면 앞에 실행된 것을 전부다 취소한다
MemberServiceTest
class MemberServiceTest {
MemberService memberService;
MemoryMemberRepository memoryMemberRepository;
@BeforeEach
public void beforeEach(){
//같은 MemoryMemberRepository 를 사용한다 이럴경우 같은 DB를 공유한다
memoryMemberRepository = new MemoryMemberRepository();
memberService=new MemberService(memoryMemberRepository);
}
@AfterEach
public void afterEach(){
memoryMemberRepository.clearStore(); // DB값 초기화
}
//...
}
- @Transactional 을 이용해서 @BeforeEach @AfterEach 을 안사용해도 된다
- 테스트를 반복해서 사용할수 있다
정리
- @SpringBootTest을 사용하면 스프링 컨테이너와 테스트를 함께 실행한다.
- @Transactional 테스트 케이스에 이 에노테이션이 있으면 테스트 시작전에 트랜잭션을 시작하고 테스트 완료후에 항상 롤백한다
- DB에 데이터가 남아있지 않아서 다음테스트에 영향을 안준다
3.스프링 JdbcTemplate
JdbcTemplateMemberRepository
public class JdbcTemplateMemberRepository implements MemberRepository {
private final JdbcTemplate jdbcTemplate;
public JdbcTemplateMemberRepository(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Member save(Member member) {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
Map<String, Object> parameters = new HashMap<>();
parameters.put("name", member.getName());
Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
member.setId(key.longValue());
return member;
}
@Override
public Optional<Member> findById(Long id) {
List<Member> result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id);
return result.stream().findAny();
}
@Override
public List<Member> findAll() {
return jdbcTemplate.query("select * from member", memberRowMapper());
}
@Override
public Optional<Member> findByName(String name) {
List<Member> result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
return result.stream().findAny();
}
private RowMapper<Member> memberRowMapper() {
return (rs, rowNum) -> {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return member;
};
}
}
SpringConfig
@Configuration
public class SpringConfig {
...
@Bean
public MemberRepository memberRepository(){
//return new MemoryMemberRepository();
//return new JdbcMemberRepository(dataSource);
return new JdbcTemplateMemberRepository(dataSource);
}
}
- new JdbcTemplateMemberRepository(dataSource) 바꾸어준다음 테스트 실행해본다!
- 테스트의 장점 직접스프링빈등록의 장점
4.JPA
- JPA는 기본 반복코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행해준다
- SQL과 데이터 중심의 설계에서 객체중심의 설계로 패러다임을 전환
- 개발의 생산성을 높인다
Member
@Entity
public class Member {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
//@Column(name = "username")
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;
}
}
- @Entity 이클래스를 테이블과 매핑한다
- @Id 기본키설정
- @GeneratedValue(strategy = GenerationType.IDENTITY) DB가 알아서 생성
- @Column(name = "username") 컬러명을 username으로 바꾸어준다
JpaMemberRepository
public class JpaMemberRepository implements MemberRepository{
private final EntityManager em;
public JpaMemberRepository(EntityManager em) {
this.em = em;
}
@Override
public Member save(Member member) {
em.persist(member); //DB를 생성하고 저장한다
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();
}
}
- 생성 persist
- 조회 find
- 단건조회 em.createQuery("select m from Member m where m.name = :name", Member.class)
- 모두조회 em.createQuery("select m from Member m", Member.class)
SpringConfig
@Configuration
public class SpringConfig {
EntityManager em;
@Autowired
public SpringConfig(EntityManager em) {
this.em = em;
}
@Bean
public MemberRepository memberRepository(){
//return new MemoryMemberRepository();
//return new JdbcMemberRepository(dataSource);
//return new JdbcTemplateMemberRepository(dataSource);
return new JpaMemberRepository(em);
}
}
- JpaMemberRepository 바꾸어주고 테스트 실행!
5.스프링데이터JPA
- 개발생산성증가
- 리포지토리에 구현클래스 없이 인터페이스만으로 개발
SpringDataJpaMemberRepository 인터페이스
public interface SpringDataJpaMemberRepository extends JpaRepository<Member,Long> ,MemberRepository{
@Override
Optional<Member> findByName(String name);
}
- JpaRepository<클래스,ID타입>
SpringConfig
@Configuration
public class SpringConfig {
private final MemberRepository memberRepository;
@Autowired
public SpringConfig(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Bean
public MemberService memberService(){
return new MemberService(memberRepository);
}
}
- 인터페이스가 기본적인 CRUD를 제공한다
- 페이징 기능제공
- findByName() , findByEmail() 처럼 메서드 이름 만으로 조회 기능 제공
- findByName -> select m from Member m where m.name =?
- 복잡한 동적쿼리는 Querydsl 라이브러리 사용
- 이조합으로 해결하기 어려운 쿼리는 JdbcTemplate,네이티브쿼리 사용
참고자료
728x90
'Back-End > Spring' 카테고리의 다른 글
1.객체지향설계와 스프링 (0) | 2020.12.30 |
---|---|
7.AOP (0) | 2020.12.29 |
5.순수 JDBC 접근기술 (0) | 2020.12.28 |
4.회원 관리 예제 - 웹 MVC개발 (0) | 2020.12.28 |
3.스프링빈과 의존관계 (0) | 2020.12.28 |