4 스프링 JdbcTemplate
(1) 스프링 Jdbc Template
- JDBC API에서 본 반복 코드를 대부분 제거
- SQL문은 직접 작성
- 실무에서도 사용 !
(2) 소스코드
- SpringConfig 수정 : 조립 !
/* MemberRepository를 SpringBin에 등록 */
@Bean
public MemberRepository memberRepository() {
// return new JdbcMemberRepository(dataSource);
return new JdbcTemplateMemberRepository(dataSource);
}
}
- JdbcTemplateMemberRepository.java
public class JdbcTemplateMemberRepository implements MemberRepository {
private final JdbcTemplate jdbcTemplate;
//@Autowired
/* JdbcTemplate 정의 */
public JdbcTemplateMemberRepository(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Member save(Member member) {
/* SimpleJdbcInsert를 사용하면 쿼리를 쓸 필요 없음 */
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id"); Map<String, Object> parameters = new HashMap<>();
parameters.put("name", member.getName());
/* 찾아서 key를 받고 value를 뽑아내는 것 */
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() {
/* callback으로 여기서 객체 생성 ! */
return (rs, rowNum) -> {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return member;
};
}
}
5 JPA
(1) JPA
- 기본적인 SQL 쿼리도 JPA가 직접 작성하여 실행해줌. ORM(객체, 관계형, 매핑)
- 객체 중심 설계, 개발 생산성 크게 증가시킬 수 있음
- 라이브러리 추가
- 자바 진영의 표준 인터페이스, 구현은 각 업체마다 다르게 하는 것
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
}
- 의존성 추가
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
(2) 소스코드
- Member : JPA 엔티티 매핑하기
@Entity
public class Member {
/* IDENTITY를 사용해 DB가 알아서 매핑하도록 함 */
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 시스템 상에서 고객에게 부여하는 Number
private String name; // 고객에 회원가입 시에 입력하는 Name
- JpaMemberRepository : JPA 회원 레포지토리
public class JpaMemberRepository implements MemberRepository {
private final EntityManager em;
/*JPA를 사용하려면 EntityManager를 주입받아야 함> 앞선 설정들에 의해서 가능 */
public JpaMemberRepository(EntityManager em) {
this.em = em;
}
/* JPA가 이것 만으로 쿼리를 알아서 작성하는 것 */
public Member save(Member member) {
em.persist(member);
return member;
}
public Optional<Member> findById(Long id) {
Member member = em.find(Member.class, id);
return Optional.ofNullable(member);
}
/* JPQL 객체지향 쿼리 사용
* Entity를 대상으로 쿼리 날리는 것 > 객체 자체를 select */
public List<Member> findAll() {
return em.createQuery("select m from Member m", Member.class).getResultList();
}
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();
}
}
- Memberservice 수정 : JPA를 통한 모든 데이터 변경은 트랜잭션 안에서 실행해야함
@Transactional
public class MemberService {
private final MemberRepository memberRepository;
- SpringConfig 수정 : 조립 !
private final EntityManager em;
public SpringConfig(DataSource dataSource, EntityManager em) {
this.dataSource = dataSource;
this.em = em;
}
/* MemberRepository를 SpringBin에 등록 */
@Bean
public MemberRepository memberRepository() {
// return new JdbcMemberRepository(dataSource);
// return new JdbcTemplateMemberRepository(dataSource);
return new JpaMemberRepository(em);
}
6 스프링 데이터 JPA
(1) 스프링 데이터 JPA
- 개발 생산성 대폭 증가, 코드량 감소
- 리포지토리에 구현 클래스 없이 인터페이스 만으로 개발을 완료할 수 있음
- 스프링 데이터 JPA는 JPA를 편리하게 사용하도록 도와주는 기술!
- 인터페이스를 통한 기본적인 CRUD 기능, 페이징 기능 제공
(2) 소스코드
- SpringConfig 수정
/* 인터페이스만 만들어놓으면 알아서 매칭됨 */
private final MemberRepository memberRepository;
public SpringConfig(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
/* MemberRepository를 SpringBin에 등록 */
@Bean
public MemberRepository memberRepository() {
// return new JdbcMemberRepository(dataSource);
// return new JdbcTemplateMemberRepository(dataSource);
// return new JpaMemberRepository(em);
return new MemberService(memberRepository);
}
- SpringDataJpaMemberRepository
/* 스프링 데이터 JPA 회원 리포지토리 */
public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
Optional<Member> findByName(String name);
}
(3) 스프링 데이터 제공 객체
> findByName을 설정해두면 인터페이스 이름만으로 쿼리 작성 완료