2021. 8. 18. 08:00ใBack-End ์์ ์ค/Spring Framework
์๋ ํ์ธ์? ์ฃผ๋ํ๋ ์ ๋๋ค.
์ค๋์ JPA์ ๋ํด ๊ณต๋ถ ํด ๋ณด๋๋ก ํ ๊ฒ์ด์์.
๋ฐ๋ก ์์ ํด ๋ณด๊ฒ ์ต๋๋ค!
์ฝ๋์ ๊ด๋ จํ ๋ด์ฉ์ ์ฃผ๋ํ๋์ Github์์ ํ์ธ ํ์ค ์ ์์ต๋๋ค!
๐ ๋ชฉ์ฐจ
01.[Spring Boot] thymeleaf์ Spring Boot
02.[Spring Boot] Spring Web ๊ฐ๋ฐ ๊ธฐ์ด
03.[Spring Boot] ํ์ ๊ด๋ฆฌ ์์ - Backend
04.[Spring Boot] Service ๊ฐ๋ฐ ๋ฐ Test Case ์์ฑ
05.[Spring Boot] Spring Bean๊ณผ ์์กด๊ด๊ณ
06.[Spring Boot] Java Code๋ก ์ง์ Spring Bean ๋ฑ๋ก
07.[Spring Boot] ๋ฑ๋ก, ๋ชฉ๋ก ๋ณด๊ธฐ ๊ตฌํํ๊ธฐ
08.[Spring Boot] ๊ธฐ์กด ์ฝ๋ ์ ์๋๊ณ , ์ค์ ์ผ๋ก ๊ตฌํ Class ๋ณ๊ฒฝ
09.[Spring Boot] ํตํฉ Test
10.[Spring Boot] JPA
11.[Spring Boot] Spring Data JPA
12.[Spring Boot] AOP
๐ Java Code๋ก ์ง์ Spring Bean ๋ฑ๋ก
JPA๋ ๊ธฐ์กด์ ๋ฐ๋ณต Code๋ ๋ฌผ๋ก ์ด๊ณ , ๊ธฐ๋ณธ์ ์ธ SQL๋ JPA๊ฐ ์ง์ ๋ง๋ค์ด์ ์คํ์ ํด ์ฃผ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐ์๊ฐ Code์ SQL๋ฌธ์ ์์ฑํ ์ผ์ด ์ ์ด์ง๋ ๊ฒ์ด ํน์ง์ธ ๊ฒ์ด์์.
JPA๋ฅผ ์ฌ์ฉํ๋ฉด SQL๊ณผ Data ์ค์ฌ์ ์ค๊ณ์์ ๊ฐ์ฒด ์ค์ฌ์ ์ค๊ณ๋ก ํจ๋ฌ๋ค์์ ์ ํํ ์ ์๋ ๊ฒ์ด์์. ๊ทธ๋ ๊ฒ ๋๋ฉด ๊ฐ๋ฐ ์์ฐ์ฑ์ ํฌ๊ฒ ๋์ผ ์ ์๋ค๋ ์ฅ์ ์ด ์๋ต๋๋ค!
JPA๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ์์กด์ฑ์ ์ถ๊ฐํด์ค์ผ ํ๋ ๊ฒ์ด์์.
build.gradle
plugins {
id 'org.springframework.boot' version '2.5.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '2.4.1'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
dependencis์ implementation์ผ๋ก starter-data-jpa๋ฅผ ์ถ๊ฐ ํด ์ค ๊ฒ์ด์์.
์ด ์์กด์ฑ์๋ jdbc ๊ด๋ จ Library๋ ํฌํจ ๋์ด ์๊ธฐ ๋๋ฌธ์ starter-jdbc๋ ์ง์๋ ์๊ด ์์ง๋ง, ์ฃผ๋ํ๋์ ๊ทธ๋๋ก ๋ฉ๋ ๊ฒ์ด์์.
๊ทธ ๋ฐ์ ์๋ ๋ด์ฉ์ mariaDB๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ์์กด์ฑ์ ์ถ๊ฐํ ๊ฒ์ด๋๋๋ค!
๐ Spring Boot JPA Config Insert
resources/application.properties
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://[dbms_ip&port]/SpringStudy?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true
spring.datasource.username=junyharang
spring.datasource.password=ํจ์ค์๋
spring.jackson.property-naming-strategy=SNAKE_CASE
spring.jpa.show_sql = true
spring.jap.hibernate.ddl-auto=none
โ ๏ธ ์ฃผ์
Spring Boot 2.4๋ถํฐ๋ spring.datasource.username='DB ID' ๋ฑ๊ณผ ๊ฐ์ด DB ์ ์ ์ ๋ณด๋ฅผ ์ ๋ ฅ ํด์ผ ํ๋ค.
show-sql : JPA๊ฐ ์์ฑํ๋ SQL๋ฌธ ์ถ๋ ฅ
ddl-auto : JPA๋ Table์ ์๋์ผ๋ก ์์ฑํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋๋ฐ, none์ ์ฌ์ฉํ๋ฉด ํด๋น ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ง ์๊ฒ ๋๋ค.
none์ด ์๋ create๋ฅผ ์ฌ์ฉํ๋ฉด Entity ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก Table๋ ์ง์ ์์ฑ
๐ JPA Entity Mapping
Member.java
package hello.hellospring.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Member {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
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;
}
} // Class ๋
๐ JPA Primary Key Mapping ์ ๋ต
JPA์๋ ๊ธฐ๋ณธ ํค ๋งคํ ์ ๋ต์ด ํฌ๊ฒ 4๊ฐ์ง๊ฐ ์๋ ๊ฒ์ด์์.
- ์ง์ ํ ๋น : ๊ธฐ๋ณธ ํค๋ฅผ Application์์ ์ง์ Entity Class์ @Id ํ๋์ set
@Id๋ง ์ฌ์ฉ - ์๋ ์์ฑ : ๋๋ฆฌํค ์ฌ์ฉ ๋ฐฉ์
@Id ์ @GeneratedValue ๊ฐ์ด ์ฌ์ฉ
- IDENTITY : ๊ธฐ๋ณธ ํค ์์ฑ์ DB์ ์์ (์ : MySQL, PostgreSQL, Server DB2 ๋ฑ - Auto_Increment ๋ฑ)
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- id ๊ฐ์ null๋ก Query๋ฅผ ๋ ๋ฆฌ๋ฉด DB๊ฐ ์์์ Auto_Increment๋ฅผ ์๋
- Auto_Increment๋ DB์ INSERT SQL Query๊ฐ ์คํ๋ ๋ค id ๊ฐ์ ์ ์ ์๋ค.
- id ๊ฐ์ DB์ ๊ฐ์ด ๋ค์ด๊ฐ ๋ค์์ผ ์ ์ ์๋ค.
- ๋ฌธ์ ์ : id ๊ฐ์ด DB์ ๋ค์ด๊ฐ ๋ค์ ์๊ฒ ๋๋ค๋ฉด?
- ์์์ฑ ์ปจํ
์คํธ์์ ํด๋น ๊ฐ์ฒด๊ฐ ๊ด๋ฆฌ๋๋ ค๋ฉด ๋ฌด์กฐ๊ฑด Primary Key ๊ฐ์ด ์์ด์ผ ํ๋ค.
์ด ๊ฒฝ์ฐ Primary Key ๊ฐ์ DB์ ๋ค์ด๊ฐ๋ด์ผ ์ ์ ์๋ค. - IDENTITY ์ ๋ต์ ๊ฒฝ์ฐ ์์์ฑ ์ปจํ
์คํธ์ 1์ฐจ Cache์์ ์๋ @Id ๊ฐ์ DB์ ๋ฃ๊ธฐ ์ ๊น์ง Setting์ด ๋ถ๊ฐ
(JPA ์ ์ฅ์์ Map์ Key ๊ฐ์ด ์์ผ๋๊น ํด๋น ๊ฐ์ฒด์ ๊ฐ์ ๋ฃ์ ์ ์๋ ๋ฐฉ๋ฒ ์์)
- ์์์ฑ ์ปจํ
์คํธ์์ ํด๋น ๊ฐ์ฒด๊ฐ ๊ด๋ฆฌ๋๋ ค๋ฉด ๋ฌด์กฐ๊ฑด Primary Key ๊ฐ์ด ์์ด์ผ ํ๋ค.
- ํด๊ฒฐ์ฑ
- IDENTITY ์ ๋ต์์๋ง ์์ธ์ ์ผ๋ก entityManager.persist()๊ฐ ํธ์ถ๋๋ ์์ ์ ๋ฐ๋ก DB์ INSERT Query๋ฅผ ๋ ๋ฆฌ๋ ๋ฐฉ๋ฒ
๋ค๋ฅธ ์ ๋ต์์๋ ์ด๋ฏธ id ๊ฐ์ ์๊ณ ์๊ธฐ์ commit gksms tlwjadp INSERT Query๋ฅผ ๋ ๋ฆฐ๋ค. - ์ ๊ณผ์ ์ ํตํด entityManager.persist()๊ฐ ํธ์ถ๋์๋ง์ INSERT Query๋ฅผ ํตํด DB์์ ์๋ณ์๋ฅผ ์กฐํํ์ฌ
์์์ฑ ์ปจํ ์คํธ์ 1์ฐจ Cache ๊ฐ์ ๋ฃ๋๋ค. (SELECT ๋ฌธ์ ๋ค์ ๋ ๋ฆฌ์ง ์์๋ ๋๋ ์ฅ์ )
- IDENTITY ์ ๋ต์์๋ง ์์ธ์ ์ผ๋ก entityManager.persist()๊ฐ ํธ์ถ๋๋ ์์ ์ ๋ฐ๋ก DB์ INSERT Query๋ฅผ ๋ ๋ฆฌ๋ ๋ฐฉ๋ฒ
- ๋จ์ : ํ๊บผ๋ฒ์ ๋ชจ์ ๋ค INSERT ํ๋ ๊ฒ์ด ๋ถ๊ฐ
- ์ด ๊ฒฝ์ฐ ๋ฒํผ๋ง์ ํด์ Write๋ฅผ ํ๋ ๊ฒ์ด ํฐ ์ฅ์ ์ด ์๊ธฐ ๋๋ฌธ์ ํฌ๊ฒ ์ ๊ฒฝ์ฐ์ง ์์๋ ๋จ.
- ํ๋์ Transaction ์์์ ์ฌ๋ฌ INSERT Query๊ฐ Network๋ฅผ ํ๋ค๊ณ ํด์ ์์ฒญ๋๊ฒ ์ฑ๋ฅ์ด ์ข์์ง์ง ์์
-
// H2 crate table Member ( id varchar(255) generated by default as identity, ... ) // MySQL create table Member ( id varchar(255) auto_increment, ... )โ
- IDENTITY ์ ๋ต์ entityManager.persist() ์์ ์ ์ฆ์ INSERT SQL Query๋ฅผ ์คํํ๊ณ , DB ์๋ณ์ ์กฐํ
- JPA๋ ๋ณดํต Transation commit ์์ ์ INSERT SQL Query ์คํ
- IDENTITY ์
- JPA๋ ๋ณดํต Transation commit ์์ ์ INSERT SQL Query ์คํ
- SEQUENCE : DB SEQUNCE๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ๋ณธ ํค ํ ๋น (์ - Oracle sequence ๋ฑ)
- TABLE : ํค ์์ฑ Table ์ฌ์ฉ (์ : Sequnce์ ์ฌ์ฉํ๋ Table์ ์ฌ์ฉํ์ฌ Table์ ๊ธฐ๋ณธํค ์ ์ฅ ๋ฐ ๊ด๋ฆฌ
- IDENTITY : ๊ธฐ๋ณธ ํค ์์ฑ์ DB์ ์์ (์ : MySQL, PostgreSQL, Server DB2 ๋ฑ - Auto_Increment ๋ฑ)
๐ Entity Manager
EntityManger๋ Entity๋ฅผ ๊ด๋ฆฌํ๋ ์ญํ ์ ์ํํ๋ Class์ธ ๊ฒ์ด์์.
EntityManger๋ ๋ด๋ถ์ ์์์ฑ ์ปจํ ์คํธ(Persistence Context)๋ผ๋ ๊ฑธ ๋์ด ๊ด๋ฆฌ ํ๋ต๋๋ค!
๐ Persistence Context(์์์ฑ ์ปจํ ์คํธ)๋?
์์์ฑ์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ปดํจํฐ ๊ณตํ์์ ์ด์ผ๊ธฐํ๋ ์์์ฑ์ธ๋ฐ, ์ด๊ฒ์ ๋น ํ๋ฐ์ฑ์ผ๋ก ๋ณผ ์ ์๋ ๊ฒ์ด์์.
ํ๋ฐ์ฑ์ ์ปดํจํฐ์ ์ ์์ด ๋๊ฐ๋ฉด Data๊ฐ ๋ชจ๋ ๋ ์์ง๋ง, ๋น ํ๋ฐ์ฑ์ ๊ทธ๋ ์ง ์์ ๊ฒ์ด์ง์.
์ด๋ฐ ํ๋ฐ์ฑ, ๋น ํ๋ฐ์ฑ์ด๋ ๋จ์ด๋ ์ ์ฅ ์ฅ์น (Memory ๋ฑ)์์ ์ฌ์ฉํ๋ ์ฉ์ด์ด๊ณ , DB์์๋ ์์์ฑ์ด๋ผ๋ ๋จ์ด๋ฅผ ์ฌ์ฉํ๋ต๋๋ค!
๊ฒฐ๊ตญ ์์์ฑ ์ปจํ ์คํธ๋ Entity๋ฅผ ์๊ตฌํ ์ ์ฅํ๋ ํ๊ฒฝ์ด๋ผ๊ณ ๋ณด๋ฉด ๋๋ ๊ฒ์ด์์.
JPA๋ Entity Manager์ ์์์ฑ ์ปจํ ์คํธ๋ฅผ ํตํด Data์ ์ํ ๋ณํ๋ฅผ ๊ฐ์งํ๊ณ , ํ์ํ Query๋ฅผ ์ํํ๋ ๊ฒ์ด์์.
mybatis์ฒ๋ผ ์ง์ SQL Query๋ฅผ ์์ฑํ๊ฑฐ๋, JPA๋ฅผ ํ์ฉํ ๊ฐ๋ฐ์ ๋์ ๋ณด์ด๋ ๊ฒ ์ด์์ ์ฐจ์ด๊ฐ ์๋ต๋๋ค!
๊ทธ ์๋ก CRUD๋ก ๋ถ๋ฆฌ๋ ๊ธฐ๋ณธ์ 4๊ฐ์ง ๋์ ์ค UPDATE๋ JPA์ ์กด์ฌํ์ง ์์ ๊ฒ์ด์์.
ํ์ง๋ง, JPA๋ Update๋ฅผ ์ ๋์ ์ํจ๋ต๋๋ค.
์ด๊ฒ์ ์์์ฑ ์ปจํ ์คํธ๊ฐ Data์ ๋ณ๊ฒฝ์ ๊ฐ์งํ์ฌ ์๋์ผ๋ก Update Query๋ฅผ ๋ ๋ ค์ฃผ๊ธฐ ๋๋ฌธ์ด์์.
๐ JPA ํ์ Repository
JpaMemberRepository.java
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;
} // JpaMemberRepository() ๋
@Override
public Member save(Member member) {
em.persist(member);
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> reulst = em.createQuery("select m from Member m where m.name = :name", Member.class).setParameter("name", name).getResultList();
return reulst.stream().findAny();
}
@Override
public List<Member> findAll() {
// List<Member> result = em.createQuery("select m from Member m", Member.class).getResultList();
// return result;
// ์์ ์ฝ๋๋ฅผ ๋จ์ํ ํ ๊ฒ
return em.createQuery("select m from Member m", Member.class).getResultList();
}
}
๐ Service Layer Taransational Insert
MemberService.java
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
// ์ปดํฌ๋ํธ ์ค์บ ๋ฐฉ์์ Service
//@Service
@Transactional
public class MemberService { // Service ์ชฝ์ ๋น์ฆ๋์ค ์ฉ์ด์ ๋ง๊ฒ ์ด๋ฆ ๋ฑ์ ์ ์ด์ผ ํ๋ค.
// ์๋ ๋ด์ฉ์์ repository ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , Service Test์์ ๋ new๋ฅผ ํตํด Repository๋ฅผ ์์ฑํด์ ํ
์คํธํ๋ฉด ์๋ก ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ด์ฉํ๊ฒ ๋๋ค.
// private final MemoryMemberRepository memberRepository = new MemoryMemberRepository();
// ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ์๋์ ๊ฐ์ด ์์ฑ์๋ฅผ ํตํด ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋๋ก ํด ์ค๋ค.
private final MemberRepository memberRepository;
// @Service๊ฐ ์๋ Service๊ฐ ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋, @Autowired๊ฐ ๋ถ์ ์์ฑ์๋ ์คํ๋ง์ด ์ปจํ
์ด๋์์ ๋น์ผ๋ก ๊ด๋ฆฌํ ๋, ์์ฑ์๋ฅผ ํธ์ถํ๋๋ฐ, ์ด ๋ MemberService๋ฅผ ๋ฃ์ด์ค๋ค.
// @Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
} // ์์ฑ์ ๋
// ํ์ ๊ฐ์
public Long join(Member member) {
// ๊ฐ์ ์ด๋ฆ์ด ์๋ ์ค๋ณต ํ์ ๊ฐ์
๋ฐฉ์ง
// Optional<Member> result = memberRepository.findByName(member.getName());
//
// result.ifPresent(memeber -> { // ifPresent๋ ํด๋น ๊ฐ์ด Null์ด ์๋๊ณ , ์ด๋ค ๊ฐ์ด ์์ผ๋ฉด ๋์ (Option๋ก ๊ฐ์ธ๋ฉด ์ฌ์ฉ ๊ฐ๋ฅ)
// throw new IllegalStateException("์ด๋ฏธ ์กด์ฌํ๋ ํ์ ์
๋๋ค.");
// });
// ์์ ์ฝ๋ ๋ณด๋ค ๋ ์ข์ ์ฝ๋
// memberRepository.findByName(member.getName()).ifPresent(member1 -> {
// throw new IllegalStateException("์ด๋ฏธ ์กด์ฌํ๋ ํ์ ์
๋๋ค.")
// });
// ์์ ์ฝ๋๋ฅผ Methodํ ํ๋ ๊ฒ์ด ์ข๋ค.
// ํด๋น ์ฝ๋๋ฅผ ๋ชจ๋ ์ ํํ๊ณ , Command + Option + M์ ๋๋ฌ์ค๋ค.
validateDuplicationMember(member); // ์ค๋ณต ํ์ ๊ฒ์ฆ
memberRepository.save(member);
return member.getId();
} // join() ๋
private void validateDuplicationMember(Member member) {
// ์์ ์ฝ๋ ๋ณด๋ค ๋ ์ข์ ์ฝ๋
memberRepository.findByName(member.getName()).ifPresent(member1 -> {
throw new IllegalStateException("์ด๋ฏธ ์กด์ฌํ๋ ํ์ ์
๋๋ค.");
});
} // validateDuplicationMember() ๋
public List<Member> findMembers() {
return memberRepository.findAll();
} // findMembers() ๋
public Optional<Member> findOne(Long memberId) {
return memberRepository.findById(memberId);
} // findOne() ๋
} // Class ๋
@Transational์ org.springframework.transaction.annotation.Transactional๋ฅผ Importํ๋ฉด ๋๋ ๊ฒ์ด์์.
Spring์ ํด๋น Class์ Method๋ฅผ ์คํํ ๋, Tansation์ ์์ํ๊ณ , Method๊ฐ ์ข ๋ฃ๋๋ฉด Transation์ Commitํ๋ ๊ฒ์ด์์.
๋ง์ฝ Run Time Error๊ฐ ๋๋ค๋ฉด? Roll Back์ ํ๋ต๋๋ค!
JPA๋ฅผ ํตํ ๋ชจ๋ Data ๋ณ๊ฒฝ์ Transation์์์ ์คํํด์ผ ํ๋ค๋ ์ ๊ธฐ์ตํด์ผ ๋๋ ๊ฒ์ด์์!
๐ JPA๋ฅผ ์ฌ์ฉํ๋๋ก Spring Config Modifie
SpringConfig.java
package hello.hellospring;
import hello.hellospring.repository.JdbcMemberRepository;
import hello.hellospring.repository.JdbcTemplateMemberRepository;
import hello.hellospring.repository.JpaMemberRepository;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
@Configuration
public class SpringConfig {
private DataSource source;
private EntityManager em;
@Autowired
public SpringConfig(DataSource source, EntityManager em) {
this.source = source;
this.em = em;
} // ์์ฑ์ ๋
// @Bean : Bean์ ๋ด๊ฐ ์ง์ ๋ง๋ค๊ฒ ๋ค๋ ์๋ฏธ; ์คํ๋ง์ ์ด๊ฒ์ ๋ณด๊ณ , Bean์ ๋ฑ๋กํ๋ผ๋ ๋ช
๋ น์ผ๋ก ์ธ์
@Bean
// ์๋ Method๋ฅผ ํธ์ถํ์ฌ Bean์ ๋ฑ๋ก
public MemberService memberService() {
// MeberService๋ฅผ ์์ฑํ๋ฉด์ memberRepository๋ฅผ Spring Bean์ ๋ฑ๋ก ๋ ์ฃผ์
ํ์ฌ ์ค๋ค.
return new MemberService(memberRepository());
} // memberService() ๋
@Bean
public MemberRepository memberRepository() {
// return new MemoryMemberRepository();
// return new JdbcMemberRepository(source);
// return new JdbcTemplateMemberRepository(source);
return new JpaMemberRepository(em);
} // memberRepository() ๋
} // Class ๋
์ฃผ๋ํ๋์ ๊ธ์ด ๋ง์์ ๋์ จ๋์? ๊ตฌ๋ ๊ณผ ๊ณต๊ฐ! ๊ทธ๋ฆฌ๊ณ , ๋๊ธ์ ์ฃผ๋ํ๋์๊ฒ ๋ง์ ํ์ด ๋ฉ๋๋ค
'Back-End ์์ ์ค > Spring Framework' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring Boot] AOP (0) | 2021.08.20 |
---|---|
[Spring Boot] Spring Data JPA (0) | 2021.08.19 |
[Spring Boot] ํตํฉ Test (0) | 2021.08.17 |
[Spring Boot] ๊ธฐ์กด ์ฝ๋ ์ ์๋๊ณ , ์ค์ ์ผ๋ก ๊ตฌํ Class ๋ณ๊ฒฝ (0) | 2021.08.15 |
[Spring Boot] ๋ฑ๋ก, ๋ชฉ๋ก ๋ณด๊ธฐ ๊ตฌํํ๊ธฐ (0) | 2021.08.14 |