์คํ๋ง DB ์ ๊ทผ ๊ธฐ์
1) H2 ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค์น
์๋์ฐ ์คํ : h2.bat
์ฝ์์์ test.mv.db ํ์ผ ์์ฑํ๊ธฐ
์ ์ ์ jdbc:h2:tcp://localhost/~/test
ํ๋ก์ ํธ ๋ฃจํธ์ sql/ddl.sql ํ์ผ๋ก sql ๋ช
๋ น์ด ๊ด๋ฆฌํ๋ฉด ํธ๋ฆฌํ๋ค.
2) ์์ JDBC
build.gradle ํ์ผ์ jdbc, h2 ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'com.h2database:h2'
์คํ๋ง ๋ถํธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ค์ ์ถ๊ฐ
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
์ฃผ์!: ์คํ๋ง๋ถํธ 2.4๋ถํฐ๋ spring.datasource.username=sa ๋ฅผ ๊ผญ ์ถ๊ฐํด์ฃผ์ด์ผ ํ๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด Wrong user name or password ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. ์ฐธ๊ณ ๋ก ๋ค์๊ณผ ๊ฐ์ด ๋ง์ง๋ง์ ๊ณต๋ฐฑ์ด ๋ค์ด๊ฐ๋ฉด ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. spring.datasource.username=sa ๊ณต๋ฐฑ ์ฃผ์, ๊ณต๋ฐฑ์ ๋ชจ๋ ์ ๊ฑฐํด์ผ ํ๋ค.
JdbcMemberRepository save ๋ฉ์๋ ์๋์ฝ๋
@Override
public Member save(Member member) {
String sql = "insert into member(name) values(?)";
Connection connection = dateSource.getConnection();
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, member.getName());
pstmt.executeUpdate();
return null;
}
Jdbc๋ฅผ ์ฌ์ฉํ ์ฝ๋ ๋๋ฌด ๊ธธ์ด์ ์ ๋ฆฌ์์ ์๋ต
*๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ : ์คํ๋ง ์ปจํ
์ด๋์์ ๋คํ์ฑ์ ์ง์ํด์ฃผ๋ฏ๋ก ์์กด์ฑ ์ฃผ์
๊ฐ๋ฅ
์ด์
๋ธ๋ฆฌ ์ฝ๋๋ง ์์ ํด๋ ๋ชจ๋ ๋ณ๊ฒฝ๋๋ค.
DataSource๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ปค๋ฅ์
์ ํ๋ํ ๋ ์ฌ์ฉํ๋ ๊ฐ์ฒด๋ค. ์คํ๋ง ๋ถํธ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ปค๋ฅ์
์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก DataSource๋ฅผ ์์ฑํ๊ณ ์คํ๋ง ๋น์ผ๋ก ๋ง๋ค์ด๋๋ค. ๊ทธ๋์ DI๋ฅผ ๋ฐ์ ์ ์๋ค.
~SOLID ์ค OCP, ๊ฐ๋ฐฉ ํ์ ์์น : DI
์คํ๋ง ํตํฉ ํ
์คํธ
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {
@Autowired MemberService memberService;
@Autowired MemberRepository memberRepository;
@Test
public void ํ์๊ฐ์
() throws Exception {
//Given
Member member = new Member();
member.setName("hello");
//When
Long saveId = memberService.join(member);
//Then
Member findMember = memberRepository.findById(saveId).get();
assertEquals(member.getName(), findMember.getName());
}
@Test
public void ์ค๋ณต_ํ์_์์ธ() throws Exception {
//Given
Member member1 = new Member();
member1.setName("spring");
Member member2 = new Member();
member2.setName("spring");
//When
memberService.join(member1);
IllegalStateException e = assertThrows(IllegalStateException.class,
() -> memberService.join(member2));//์์ธ๊ฐ ๋ฐ์ํด์ผ ํ๋ค.
assertThat(e.getMessage()).isEqualTo("์ด๋ฏธ ์กด์ฌํ๋ ํ์์
๋๋ค.");
}
}
@SpringBootTest : ์คํ๋ง ์ปจํ
์ด๋์ ํ
์คํธ๋ฅผ ํจ๊ป ์คํํ๋ค.
@Transactional : ํ
์คํธ ์ผ์ด์ค์ ์ด ์ด๋
ธํ
์ด์
์ด ์์ผ๋ฉด, ํ
์คํธ ์์ ์ ์ ํธ๋์ญ์
์ ์์ํ๊ณ , ํ
์คํธ ์๋ฃ ํ์ ํญ์ ๋กค๋ฐฑํ๋ค. ์ด๋ ๊ฒ ํ๋ฉด DB์ ๋ฐ์ดํฐ๊ฐ ๋จ์ง ์์ผ๋ฏ๋ก ๋ค์ ํ
์คํธ์ ์ํฅ์ ์ฃผ์ง ์๋๋ค
๋จ์ํ
์คํธ๊ฐ ํตํฉํ
์คํธ๋ณด๋ค ๋ ํจ์จ์ ์ผ ๊ฐ๋ฅ์ฑ์ด ๋๋ค
Jdbc Templeate
- Mybatis์ ์ ์ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ~ ์์ Jdbc์์ ๋ฐ๋ณต๋๋ ์ฝ๋๋ฅผ ๋๋ถ๋ถ ์ ๊ฑฐํด์ฃผ์ง๋ง, SQL์ ์ง์ ์์ฑํด์ผํ๋ค.
์์ฑ์๊ฐ ํ๋์ธ ๊ฒฝ์ฐ @Autowired ์ด๋
ธํ
์ด์
์ ํตํ ์์กด์ฑ ์ฃผ์
์์ ์ด๋
ธํ
์ด์
์ ์๋ต์ด ๊ฐ๋ฅํ๋ค
- ์ Templeate์ธ๊ฐ? -> ๋์์ธ ํจํด ์ค ํ
ํ๋ฆฟ ๋ฉ์๋ ํจํด์ ๋ง์ด ์ฌ์ฉํ๊ธฐ ๋๋ฌธ
JPA
Jdbc Templeate์์ SQL ์ฟผ๋ฆฌ๋ JPA๊ฐ ์คํํด์ค๋ค ~ ๊ฐ์ฒด ์ค์ฌ์ ์ค๊ณ๋ก ํจ๋ฌ๋ค์์ ์ ํํ ์ ์๋ค
- build.gradle
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
- application.properties
# show-sql : JPA๊ฐ ์์ฑํ๋ SQL์ ์ถ๋ ฅํ๋ค
spring.jpa.show-sql=true
# ddl-auto : JPA๋ ํ
์ด๋ธ์ ์๋์ผ๋ก ์์ฑํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋๋ฐ none์ ์ฌ์ฉํ๋ฉด
# ํด๋น ๊ธฐ๋ฅ์ ๋๋ค ~ create๋ฅผ ์ฌ์ฉํ๋ฉด ์ํฐํฐ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ํ
์ด๋ธ๋ ์ง์ ์์ฑํด์ค๋ค
spring.jpa.hibernate.ddl-auto=none
JPA๋ ์ธํฐํ์ด์ค๊ณ , Hibernate๊ฐ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ ๊ตฌํ์ฒด
JPQL : ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฐ๋ค
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import javax.persistence.EntityManager;
import java.util.List;
import java.util.Optional;
public class JpaMemberRepository implements MemberRepository {
private final EntityManager em;
public JpaMemberRepository(EntityManager em) {
this.em = em;
}
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);
}
public List<Member> findAll() {
return em.createQuery("select m from Member m", Member.class)
.getResultList();
}
// ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๋ JPQL
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();
}
}
JPA๋ฅผ ํตํ ๋ชจ๋ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ Transactional ๋จ์๋ก ์คํ๋์ด์ผ ํ๋ค.
Spring Data JPA
์คํ๋ง ๋ฐ์ดํฐ JPA๋ JPA๋ฅผ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ๋๋ก ๋์์ฃผ๋ ๊ธฐ์ ์
๋๋ค. ๋ฐ๋ผ์ JPA๋ฅผ ๋จผ์ ํ์ตํ ํ ์คํ๋ง ๋ฐ์ดํฐ JPA๋ฅผ ํ์ตํด์ผ ํฉ๋๋ค.
*JPA Repository๋ฅผ ์์ํ ๋ ์ฌ์ฉํ๋ ์ ๋ค๋ฆญ์ค : <์ํฐํฐ, ์๋ณ์ ํ์
>
+ Spring Data JPA๊ฐ JPA Repository๋ฅผ ์์ํ๋ ๋ ํฌ์งํ ๋ฆฌ์ ๊ตฌํ์ฒด๋ฅผ ์๋์ผ๋ก ์คํ๋ง ๋น์ ๋ฑ๋กํด์ค๋ค
๊ตฌํ์ฒด๋ฅผ ๋ง๋ค ๋ ํ๋ก์๋ก ๋ง๋ ๋ค
- Spring Data JPA ์ ๊ณต ๊ธฐ๋ฅ
- ์ธํฐํ์ด์ค๋ฅผ ํตํ ๊ธฐ๋ณธ CRUD
- findByName(), findByEmail() ๋ฑ ๋ฉ์๋ ์ด๋ฆ๋ง์ผ๋ก ์กฐํ ๊ธฐ๋ฅ ์ ๊ณต
- ํ์ด์ง ๊ธฐ๋ฅ ์๋ ์ ๊ณต
package hello.helloSpring.repository;
import hello.helloSpring.domain.Member;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
// ์ํฐํฐ, ์๋ณ์ ํ์
public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {
// equals JPQL select m from Member m where m.name = ?
@Override
Optional<Member> findByName(String name);
}
> ์ฐธ๊ณ : ์ค๋ฌด์์๋ JPA์ ์คํ๋ง ๋ฐ์ดํฐ JPA๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๊ณ , ๋ณต์กํ ๋์ ์ฟผ๋ฆฌ๋ Querydsl์ด๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. Querydsl์ ์ฌ์ฉํ๋ฉด ์ฟผ๋ฆฌ๋ ์๋ฐ ์ฝ๋๋ก ์์ ํ๊ฒ ์์ฑํ ์ ์๊ณ , ๋์ ์ฟผ๋ฆฌ๋ ํธ๋ฆฌํ๊ฒ ์์ฑํ ์ ์๋ค. ์ด ์กฐํฉ์ผ๋ก ํด๊ฒฐํ๊ธฐ ์ด๋ ค์ด ์ฟผ๋ฆฌ๋ JPA๊ฐ ์ ๊ณตํ๋ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, ์์ ํ์ตํ ์คํ๋ง JdbcTemplate๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.