<스프링입문>06. 스프링 DB 접근 기술

박서연·2023년 3월 28일
0

Spring

목록 보기
6/10

📌 단축키

단축키 alt+shift+enter로 method implement
단축키 ctrl+alt+v로 변수 생성
단축키 ctrl+alt+n으로 inline으로 변경
단축키 alt+insert로 생성자 생성

단축키 Shift+Ctrl+Alt+T로 원하는 단축키 문자 알 수 있음

📌 H2 데이터베이스 설치

🔸 H2는 용량이 작고 웹 화면 제공

1. H2 데이터베이스 설치 및 열기

https://www.h2database.com/html/download-archive.html
🔸 1.4.200 version + All Platforms download
🔸 cmd

cd (파일경로)
cd h2-2019-10-14
cd h2
cd bin
h2.bat

💡 위 화면 URL은 http://10.14.4.69:8082/login.jsp?jsessionid=e58d773bdae1423a0193939a6ab04ed5
만약 화면 안 뜰 경우, 10.14.4.69를 localhost로 변경 나머지는 건드리지 말 것

2. 최초에만 database 파일 생성

🔸 JDBC URL: jdbc:h2:~/test
파일 경로, home에 있는 test 파일
🔸 아무 변경 없이 연결
🔸 home에 test.mv.db 파일 생성되었는지 확인
cmd에서 dir로 파일 확인

🔸 이후부터는 JDBC URL에 jdbc:h2:tcp://localhost/~/test 작성 후 연결. 위 JDBC URL과 달리 파일을 직접 접근하는 것이 아니라 socket을 통해 접근. 이럴 경우 여러 곳에서 접근 가능

3. 테이블 생성

0) 데이터베이스 연결

위에서 말한 것처럼 H2 데이터베이스 연 후 JDBC URL에 jdbc:h2:tcp://localhost/~/test 작성 후 연결

1) 테이블 생성

🔸 sql 작성
💡 sql은 Member.java와 비교
🔹 id는 java에서 long type이었는데 database안에서는 bigint type
🔹 generated by default as identity

  • 값을 세팅하지 않고 insert하면 DB가 값을 채워줌
    🔹 primary key는 id로 잡음. DB에서 자동으로 증가
drop table if exists member CASCADE;
create table member
(
 id bigint generated by default as identity,
 name varchar(255),
 primary key (id)
);

2) member 넣기

insert into member(name) values('spring')

3) 조회

🔸 sql문 모두 지운 후 MEMBER table 클릭하면 select * from member 코드 작성되어 바로 조회 가능

select * from member

🌟 SQL
ctrl+enter, shift+enter 실행

🌟 IntelliJ에 sql 디렉토리 만든 후 ddl.sql 파일 생성하면 깃 등에서 관리하기 편함

🌟 cmd 끄면 DB 동작 X. DB 연결부터 다시 해야됨

  • 지금까지는 웹 콘솔로 들어간 것. 애플리케이션에서 DB 접근한 후 데이터 넣고 뺄 것

📌 순수 JDBC

🔸 application에서 DB에 연동해서 DB에 query를 날려 data를 넣고 빼기
🔸 아주 오래 전 기술

💡 스프링의 장점
객체지향적인 설계이기에 다형성(interface를 두고 구현체 바꾸기 쉽도록)이 좋아 스프링 컨테이너가 지원(Dependency injection 사용)

🔸 MemberService는 MemberRepository에 의존. MemberRepository는 구현체로 MemoryMemberRepository와 JdbcMemberRepository 존재.

🔸 개방-폐쇄 원칙(OCP, Open-Close Principle) 적용
🔸 스프링의 DI(Dependencues Injection)을 사용하면 기존 코드를 전혀 손대지 않고, 설정만으로 구현 클래스를 변경할 수 있음. 빈만 만들면 스프링이 DI 적용해줌

📌 스프링 통합 테스트

🔸 순수 JDBC 연동 테스트

🔸 @SpringBootTest
스프링 컨테이너와 테스트를 함께 실행
🔸 @Transactional
테스트 케이스에 붙었을 경우, 테스트 시작 전에 트랜잭션을 시작하고 테스트 완료 후에 항상 롤백. DB에 데이터가 반영되지 않아 다음 테스트에 영향을 주지 않음
서비스 등 다른 곳에 붙었을 경우 롤백하지 않음

🔸 순수 자바 코드로 작성한 테스트를 단위 테스트, spring과 DB 연동까지 하는 테스트를 통합 테스트라 부름. 단위 테스트가 통합 테스트보다 좋은 테스트일 경우가 많음

📌 스프링 JdbcTemplate

🔸 JDBC의 반복 코드를 제거해주는 라이브러리. 단 SQL은 직접 작성해야함
🔸 실무에서 자주 사용
💡 생성자가 하나일 경우 @Autowired 생략 가능

📌 JPA

🔸 JDBC -> JDBCTemplate으로 바꿀 때 반복 코드 제거
하지만 SQL은 개발자가 직접 작성해야함
🔸 JPA는 SQL query를 자동으로 처리해줌
🔸 JPA 사용하면 SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환할 수 있음

1. 라이브러리 추가

1) build.gradle에 코드 추가

build.gradle

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'

2) application.properties에 코드 추가

main/.../resource/application.properties
🔸 spring.jpa.show-sql=true
JPA가 날리는 sql 볼 수 있음
🔸 spring.jpa.hibernate.ddl-auto=none
JPA는 객체를 보고 테이블을 자동으로 생성. But 이미 만들었으므로 none으로 설정

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none

2. entity mapping

🔸 JPA는 자바 표준 인터페이스고 구현은 여러 업체가 함.
JPA는 인터페이스, hibernate는 구현체 => 주로 사용
🔸 객체와 ORM(Object Relational database table Mapping)

Member.java
🔸 @Entity
JPA가 관리하는 entity
🔸 @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
pk인 Id mapping. Id는 DB에서 자동으로 값 생성됨 => IDENTITY 전략
🔸 @Column(name="username")

🏅 최종 코드_Member.java

package hello.hellospring.domain;

import javax.persistence.*;

@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;
    }
}

3. Repository 생성

main/.../repository/JpaMemberRepository.java

🔸 MemberRepository implements 후 단축키 alt+shift+enter로 method implement
🔸 private final EntityManager em; 작성 후 단축키 alt+insert로 생성자 생성
🔹 JPA는 EntityManager로 모든 것이 동작
🔹 build.gradle의 implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 라이브러리를 가져오면서 springboot가 자동으로 EntityManager를 생성하므로 injection해서 사용하면 됨. 현재 DB와 연결도 해줌
🔸 save 함수에 em.persist(member); , return member;
🔸 findById 함수에 em.find(Member.class, id); 입력 후 단축키 ctrl+alt+v로 변수 생성, return Optional.ofNullable(member);
🔸 findByName 함수에는 em.createQuery("select m from Member m where m.name =:name", Member.class) (enter) .setParameter("name", name) (enter) .getResultList(); 작성 후 단축키 ctrl+alt+v로 변수 생성 후 변수명 result로 변경. return result.stream().findAny();
🔸 findAll 함수에는 JPQL이라는 객체지향쿼리언어 사용.
em.createQuery("select m from Member m", Member.class) (enter) .getResultList(); 작성 후 단축키 ctrl+alt+v로 변수 생성. 변수명 result로 변경, return result; 작성 후 단축키 ctrl+alt+n으로 inline으로 변경

🌟 JPA는 트랜잭션이 반드시 존재해야함. @Transactional 작성. 데이터를 저장하거나 변경할 때 트랜잭션이 존재해야함

💡 단축키 shift+ctrl+alt+t로 inline 단축키 문자 알 수 있음
💡 JPQL
객체 지향 쿼리 언어. pk기반이 아닌 함수들은 JPQL을 작성해야함.
table 대상으로 쿼리 날리지 않고 객체(Entity)를 대상으로 쿼리 날리는 것. 이후 SQL로 번역됨
ex.findAll의 "select m from Member m" => 객체(entity) m 자체를 select
💡 스프링 데이터 JPA
JPA를 스프링에 감싸서 제공하는 기술

4. Config

SpringConfig.java

1) EntityManager

private EntityManager em; 작성 후 단축키 alt+insert로 생성자 생성. 생성자 위에 @Autowired 작성

2) memberRepository

🔸 위의 return 값들을 모두 없앤 후 return new JpaMemberRepository(em); 작성

📌 스프링 데이터 JPA

🔸 JPA를 편리하게 사용하도록 도와주는 기술로, JPQL로 SQL 작성하지 않아도 됨
🔸 스프링부트와 JPA 기반 위에 스프링 데이터 JPA라는 프레임워크가 더해지면 리포지토리에 구현 클래스 없이 인터페이스만으로 개발 가능
🔸 실무에서 관계형 데이터베이스를 사용한다면 스프링 데이터 JPA는 필수

1. SpringDataJpaMemberRepository

main/.../repository/SpringDataJpaMemberRepository
repository 아래에 SpringDataJpaMemberRepository 이름의 interface 생성
🔸 JpaRepository extends
스프링 데이터 JPA가 SpringDataJpaMemberRepository를 스프링 빈으로 자동 등록. 구현체를 자동으로 만들고 스프링빈에 등록

public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
    @Override
    Optional<Member> findByName(String name);
}

2. SpringConfig

🔸 memberRepository과 entityManager 관련 내용 모두 지움
🔸 private final MemberRepository memberRepository; 작성 후 단축키 alt+insert로 생성자 생성 후 생성자 위에 @Autowired

💡 인터페이스를 통한 기본적인 CRUD 제공
💡 findByName(), findByEmail()처럼 메서드 이름만으로 조회 기능 제공
💡 페이징 기능 자동 제공

0개의 댓글