Spring boot - DB제작(2)

범수·2024년 2월 21일

목차

  1. 프로젝트 생성하기
  2. View 환경설정
  3. 스프링 웹 개발 기초
  4. 회원 관리 예제
  5. 스프링 빈과 의존 관계
  6. 웹 MVC 제작
  7. DB 제작(1)
  8. DB 제작(2)
  9. AOP

4. 더 간단한 DB

JdbcTemplate

 public class JdbcTemplateMemberRepository implements MemberRepository {
 
 	private final JdbcTemplate jdbcTemplate;
    
 	public JdbcTemplateMemberRepository(DataSource dataSource) {
        jdbcTemplate = new JdbcTemplate(dataSource);
    }
    ...
 }
 
 //JdbcTemplateMemberRepository.java
  • 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;
}
 
 // JdbcTemplateMemberRepository.java > 저장 부분
  • jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
    • member테이블의 id를 자동 증가 값 추가(앞서 사용했던 id Generated Key와 같음)
  • jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
    • executeAndReturnKey 메서드는 데이터베이스에 쿼리를 실행
    • MapSqlParameterSource는 이름-값 쌍으로 매핑된 파라미터를 제공
      • parameters를 Map형태로 설정한 이유!
@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;
     };
} // memberRowMapper구현 코드
  • RowMapper는 데이터베이스의 반환 결과인 ResultSet을 객체로 변환해 주는 클래스
    • 기존 Jdbc에서는 각 값을 일일이 get해주어야하는 수고로움을 자동화 해줌
  • jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
    • sql에 맞는 name이 매칭되면 RowMapper후 매핑된 값을 반환
 @Bean
 public MemberRepository memberRepository() {
 	//return new MemoryMemberRepository();
 	//return new JdbcMemberRepository(dataSource);
 	return new JdbcTemplateMemberRepository(dataSource);
}
// SpringConfig.java
  • 스프링 컨테이너의 빈 모듈을 교체해줘야 함으로 JdbcTemplateMemberRepository(dataSource);로 교체

    테스트 정상 작동

JPA

& 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행

 implementation 'org.springframework.boot:spring-boot-starter-jdbc'
 implementation 'org.springframework.boot:spring-boot-starter-data-jpa
 
 // build.gradle > dependencies
  • build.Gradle의 Dependencies jdbc에서 jpa로 수정
 spring.jpa.show-sql=true
 spring.jpa.hibernate.ddl-auto=none
 
 // application.properties
  • application.properties에 show-sql, hibernate.ddl 추가
    • show-sql=true는 JPA가 생성하는 SQL을 출력
    • hibernate.ddl-auto=none는 자동으로 테이블 생성x
      • auto=create는 엔티티 정보를 바탕으로 테이블 자동 생성
 @Entity
 public class Member {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
 	private Long id;
 	private String name;
    ...
}

// Member.java
  • @Entity는 DB 테이블과 Jpa를 매핑
    • DB에 생성했던 Member 테이블의 이름과 class의 이름으로 매핑
  • @ID는 엔티티의 기본 키 필드를 나타냄
    • DB 테이블의 기본 키 열과 매핑
  • @GeneratedValue(strategy = GenerationType.IDENTITY)는 기본 키 값을 자동으로 생성하는 옵션
  • 나머지 칼럼은 자동으로 매핑
 public class JpaMemberRepository implements MemberRepository{
 
 	private final EntityManager em; // ENtityManager 생성
    
 	public JpaMemberRepository(EntityManager em) {
 		this.em = em;
    }
    
 	public Member save(Member member) {	// 저장
        em.persist(member);	// DB 저장
 		return member;
    }
    
 	public Optional<Member> findById(Long id) {	// id로 찾기
 		Member member = em.find(Member.class, id); //@id 기반으로 검색
 		return Optional.ofNullable(member);
    }
    
 	public List<Member> findAll() {	// 모두 찾기
 		return em.createQuery("select m from Member m", Member.class)
              	.getResultList(); // alias로 전체 조회
    }
    
	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();
    }
 }
 
 // JpaMemberRepository.java
  • EntityManager: 엔티티의 영구 저장과 관리를 담당
  • persist(): 메서드는 전달된 엔티티 객체를 영구 저장소에 저장하고, 관리 상태로 전환
  • find(table.class, id): 주어진 엔티티 클래스와 @id id를 기반으로 데이터베이스에서 엔티티를 찾음
    • 회원ID 기반이 아닌 @ID로 설정한 ID로 조회
  • createQuery(sql, T.class): 테이블 클래스에 Sql 쿼리 전송
    • *대신 alias를 사용해 전체 조회

테스트 및 Hibernate=true 확인

스프링 데이터 JPA

  • 리포지토리에 구현 클래스 없이 인터페이스 만으로 개발 가능
  • CRUD 기능 제공
  • 스프링 데이터 JPA는 JPA를 편리하게 사용하도록 도와주는 기술
    • JPA 완전 이해 필요!
 public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
 	@Override
 	Optional<Member> findByName(String name);
 }
 
 // SpringDataJpaMemberRepository.java(인터페이스)
  • 스프링 데이터 JPA가 SpringDataJpaMemberRepository를 스프링 빈으로 자동 등록
    • 인터페이스를 보고 자동으로 등록해줌
  • JpaRepository는 기본적으로 사용되는 조회, 저장, 삭제 등을 포함하고 있음
    • findBy(컬럼명) 등으로 간단하게 기본적인 조회 가능
	...
 private final MemberRepository memberRepository;
 
 public SpringConfig(MemberRepository memberRepository) {
 	this.memberRepository = memberRepository;
 }
 
    @Bean
 public MemberService memberService() {
 	return new MemberService(memberRepository);
 }
 	...
    
 // SpringConfig.java
  • memberRepository만 등록해주면 자동으로 JPA로 연결가능
profile
범수의 개발 놀이터😋

0개의 댓글