JPA๋ ์๋ฐ ์ง์์์ ORM(Object-Relational Mapping) ๊ธฐ์ ํ์ค์ผ๋ก ์ฌ์ฉ๋๋ ์ธํฐํ์ด์ค์ ๋ชจ์์ด๋ค
์ค์ ์ ์ผ๋ก ๊ตฌํ๋๊ฒ์ด ์๋๋ผ ๊ตฌํ๋ ํด๋์ค์ ๋งคํ์ ํด์ฃผ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ํ๋ ์์ํฌ์ด๋ค.
JPA๋ฅผ ๊ตฌํํ ๋ํ์ ์ธ ์คํ์์ค๋ก๋ Hibernate๊ฐ ์๋ค
( JPA๋ ์ธํฐํ์ด์ค / ๊ตฌํ hibernate )
ORM(Object-Relational Mapping)
๊ฐ์ฒด-๊ด๊ณ ๋งคํ
๊ฐ์ฒด์งํฅ ์ธ์ด์ ๊ฐ์ฒด์ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ดํฐ ์ฌ์ด์์ ๋ํ๋๋ ๋ฏธ๋ฌํ ์ฐจ์ด์
์ด๋ก ์ธํ ๋ฌธ์ ๋ค์ ๊ทน๋ณตํ๊ธฐ ์ํด ๋ฑ์ฅํ ๊ธฐ์ ์ด๋ค.
์ฐ๋ฆฌ๊ฐ ์ผ๋ฐ ์ ์ผ๋ก ์๊ณ ์๋ ์ ํ๋ฆฌ์ผ์ด์ Class์ RDB(Relational DataBase)์ ํ ์ด๋ธ์ ๋งคํ(์ฐ๊ฒฐ)ํ๋ค๋ ๋ป์ด๋ฉฐ,
๊ธฐ์ ์ ์ผ๋ก๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ๊ฐ์ฒด๋ฅผ RDB ํ ์ด๋ธ์ ์๋์ผ๋ก ์์ํ ํด์ฃผ๋ ๊ฒ์ด๋ผ๊ณ ๋ณด๋ฉด๋๋ค.
SQL๋ฌธ์ด ์๋ Method๋ฅผ ํตํด DB๋ฅผ ์กฐ์
(๋ด๋ถ์ ์ผ๋ก๋ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ์ฌ DB๋ฅผ ์กฐ์ํจ. ํ์ง๋ง ๊ฐ๋ฐ์๊ฐ ์ด๋ฅผ ์ ๊ฒฝ ์ฐ์ง ์์๋๋จ)
JPA๋ ๊ธฐ์กด์ ๋ฐ๋ณต ์ฝ๋๋ ๋ฌผ๋ก ์ด๊ณ , ๊ธฐ๋ณธ์ ์ธ SQL๋ JPA๊ฐ ์ง์ ๋ง๋ค์ด์ ์คํํด์ค๋ค.
JPA๋ฅผ ์ฌ์ฉํ๋ฉด, SQL๊ณผ ๋ฐ์ดํฐ ์ค์ฌ์ ์ค๊ณ์์ ๊ฐ์ฒด ์ค์ฌ์ ์ค๊ณ๋ก ํจ๋ฌ๋ค์์ ์ ํ์ ํ ์ ์๋ค.
JPA๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ๋ฐ ์์ฐ์ฑ์ ํฌ๊ฒ ๋์ผ ์ ์๋ค.
build.gradle ํ์ผ์ JPA, h2 ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
spring-boot-starter-data-jpa ๋ ๋ด๋ถ์ jdbc ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํฌํจํ๋ค. ๋ฐ๋ผ์ jdbc๋ ์ ๊ฑฐํด๋ ๋๋ค.
์คํ๋ง ๋ถํธ์ JPA ์ค์ ์ถ๊ฐ
resources/application.properties
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
show-sql : JPA๊ฐ ์์ฑํ๋ SQL์ ์ถ๋ ฅํ๋ค.
ddl-auto : JPA๋ ํ
์ด๋ธ์ ์๋์ผ๋ก ์์ฑํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋๋ฐ none ๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น ๊ธฐ๋ฅ์ ๋๋ค.
create ๋ฅผ ์ฌ์ฉํ๋ฉด ์ํฐํฐ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ํ ์ด๋ธ๋ ์ง์ ์์ฑํด์ค๋ค. ํด๋ณด์.
JPA ์ํฐํฐ ๋งคํ
import javax.persistence.Entity;
@Entity
public class Member
@Entity
JPA์์ ์ํฐํฐ๋ ์ฝ๊ฒ ์๊ฐํ๋ฉด, DB ํ ์ด๋ธ์ ๋์ํ๋ ํ๋์ ํด๋์ค๋ผ๊ณ ์๊ฐํ ์ ์์ต๋๋ค.
@Entity๊ฐ ๋ถ์ ํด๋์ค๋ JPA๊ฐ ๊ด๋ฆฌํด์ฃผ๋ฉฐ,
JPA๋ฅผ ์ฌ์ฉํด์ DB ํ ์ด๋ธ๊ณผ ๋งคํํ ํด๋์ค๋ @Entity๋ฅผ ๊ผญ ๋ถ์ฌ์ผ๋ง ๋งคํ์ด ๊ฐ๋ฅํฉ๋๋ค.
์ํฐํฐ ํด๋์ค๋ ํ ์ด๋ธ๊ณผ ๋งคํ๋๋ ํด๋์ค์ด๋ค.
์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ ์ ํ ์ํฐํฐ ํด๋์ค๋ฅผ ๊ตฌ์ฑํ๊ณ , ์์ฑ๋ ์ํฐํฐ ํด๋์ค๋ ๋ช ์ธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ์ด๋ธ๊ณผ ๋งคํ๋๋ค.
insert into member(name) values("spring1");
์ฟผ๋ฆฌ์ id๋ฅผ ๋ฃ์ง์์์
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ๊ธฐ๋ณธ ํค(PK)์ ๊ฐ์ฒด์ ํ๋๋ฅผ ๋งคํ์์ผ์ฃผ๋ ์ด๋ ธํ ์ด์ ์ ๋๋ค.
๊ธฐ๋ณธ ํค๋ฅผ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ง์ ์ํฐํฐํด๋์ค์ @Id ํ๋์ setํด์ค๋ค.
๊ธฐ๋ณธ ํค๋ฅผ ์ง์ ํ ๋นํ๋ ๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์์ฑํด์ฃผ๋ ๊ฐ์ ์ฌ์ฉํ๋ ค๋ฉด @GeneratedValue๋ฅผ ์ฌ์ฉํด์ฃผ๋ฉด ๋ฉ๋๋ค.
@GeneratedValue
๊ธฐ๋ณธ ํค๋ฅผ ์๋ ์์ฑํด์ฃผ๋ ์ด๋ ธํ ์ด์ ์ ๋๋ค.
๊ธฐ๋ณธ ํค ์์ฑ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์
@GeneratedValue(strategy = GenerationType.IDENTITY)
-> DB์ ๊ฐ์ ๋ฃ์ผ๋ฉด DB๊ฐ id๋ฅผ ์๋์ผ๋ก ์์ฑ == IDENTITY ์ ๋ต
์ฆ, id ๊ฐ์ null๋ก ํ๋ฉด DB๊ฐ ์์์ AUTO_INCREMENT ํด์ค๋ค.
JPA ํ์ ๋ฆฌํฌ์งํ ๋ฆฌ
public class JpaMemberRepository implements MemberRepository{
private final EntityManager em;
public JpaMemberRepository(EntityManager em) {
this.em = em;
}
EntityManager
Entity
- ํ ์ด๋ธ๊ณผ ๋งค์นญ๋๋ ๊ฐ๋
- ORM ์ ์ด๋ฃจ๋ ๊ธฐ๋ฐ ๊ฐ๋ ์ค ํ๋. ๊ฐ์ฒด์ RDB ๊ฐ ์ฐ๊ฒฐ์์ผ์ฃผ๋ ์กด์ฌ
EntityManager
- ์ํฐํฐ๋ฅผ ๊ด๋ฆฌํ๋ ์ญํ ์ ํ๋ค.
JPA๋ EntityManager๋ก ๋ชจ๋ ๊ฒ์ ๋์
์คํ๋ง๋ถํธ๊ฐ ์๋์ผ๋ก EntityManager๋ฅผ ์์ฑํด์ค ( ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐ์ ๋ค ํ ์ํ )
์ฐ๋ฆฌ๋ ๋ง๋ค์ด์ง๊ฒ์ ์ธ์ ์ ๋ฐ์ผ๋ฉด ๋๋ค
[JPA] EntityManager ๋ช ๋ น์ด ์ ๋ฆฌ

@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);
}
find(class์ด๋ฆ,๊ธฐ๋ณธํค)
- EntityManager์ find() ๋ฉ์๋๋ DB๋ฅผ ํตํด์ ์ค์ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์กฐํํ๋ ๋ฉ์๋
- ํด๋นํ๋ ๊ฐ์ฒด๋ฅผ ์์์ฑ ์ปจํ ์คํธ๋ก ๊ฐ์ ธ์จ๋ค.
@Override
public List<Member> findAll() {
return em.createQuery("select m from Member as m", Member.class)
.getResultList();
}
createQuery(jpql)
jpql์ sql๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์กํ๋ค.
query.getResultList()
๊ฒฐ๊ณผ๋ฅผ ์ปฌ๋ ์ ์ผ๋ก ๋ฐํํ๋ค.
๊ฐ์ฒด(์ํฐํฐ)๋ฅผ ๋์์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฐ๋ค -> sql ๋ก ๋ฒ์ญ
from Member as m : ์ํฐํฐ๋ฅผ ์กฐํ
select m : member ์ํฐํฐ ์์ฒด๋ฅผ select
JPQL
(JPQL์ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์กฐํํ๋ ๊ฐ์ฒด์งํฅ ์ฟผ๋ฆฌ ์ธ์ด์ด๋ค.)

๊ฒฐ๊ณผ ์กฐํ
- query.getResultList()๊ฒฐ๊ณผ๋ฅผ ์ปฌ๋ ์ ์ผ๋ก ๋ฐํํ๋ค. ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด ๋น ์ปฌ๋ ์ ์ด ๋ฐํ๋๋ค. 1๊ฑด์ด๋ฉด 1๊ฑด๋ง ๋ค์ด๊ฐ ์ปฌ๋ ์ ์ด ๋ฐํ๋๋ค.
@Override
public Optional<Member> findByName(String name) {
List<Member> result = em.createQuery("select m from Member as m where m.name = :name", Member.class)
.setParameter("name", name)
.getResultList();
return result.stream().findAny();
}
query.getResultList()
๊ฒฐ๊ณผ๋ฅผ ์ปฌ๋ ์ ์ผ๋ก ๋ฐํํ๋ค.
ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ
์๋์ ๊ฐ์ ์ด๋ฆ ๊ธฐ์ค ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ์ ์ง์ํ๋ค.
TypedQuery<Member> query =
em.createQuery("SELECT m FROM Member m WHERE m.username = :username", Member.class)
.setParameter("username", "joont1"); // JPQL์ ๋๋ถ๋ถ ๋ฉ์๋ ์ฒด์ธ ๋ฐฉ์์ผ๋ก ๋์ด์์ด์ ์ด๋ ๊ฒ ์ฐ์ํด์ ์์ฑํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค
List<Member> result = query.getResultLst();
username์ Member ํด๋์ค์ ์ ์๋ ํ๋กํผํฐ ์ด๋ฆ์ด๋ค. ์์ :๋ฅผ ๋ถ์ฌ์ ๋ฐ์ธ๋ฉํ๋ค.
username ์ joont1 ์ด ๋ฐ์ธ๋ฉ ๋ ๊ฒ์ด๋ค.
JPA๋ฅผ ์ธ๋ ค๋ฉด ํธ๋์ญ์ ์ด ์์ด์ผํจ ( ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ฑฐ๋ ๋ณ๊ฒฝํ ๋ )
-> ์๋น์ค ๊ณ์ธต์ ํธ๋์ญ์ ์ถ๊ฐ
import org.springframework.transaction.annotation.Transactional
@Transactional
public class MemberService {}
์คํ๋ง์ ํด๋น ํด๋์ค์ ๋ฉ์๋๋ฅผ ์คํํ ๋ ํธ๋์ญ์ ์ ์์ํ๊ณ , ๋ฉ์๋๊ฐ ์ ์ ์ข ๋ฃ๋๋ฉด ํธ๋์ญ์ ์ ์ปค๋ฐํ๋ค.
๋ง์ฝ ๋ฐํ์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ๋กค๋ฐฑํ๋ค.
JPA๋ฅผ ํตํ ๋ชจ๋ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ํธ๋์ญ์
์์์ ์คํํด์ผ ํ๋ค.
JPA๋ฅผ ์ฌ์ฉํ๋๋ก ์คํ๋ง ์ค์ ๋ณ๊ฒฝ
public class SpringConfig {
private EntityManager em;
@Autowired
public SpringConfig(EntityManager em) {
this.em = em;
}
public MemberRepository memberRepository() {
return new JpaMemberRepository(em);
}
'Spring > Spring ์ ๋ฌธ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์คํ๋ง ์ ๋ฌธ - (19) AOP (Aspect Oriented Programming) (0) | 2023.01.29 |
---|---|
์คํ๋ง ์ ๋ฌธ - (18) ์คํ๋ง ๋ฐ์ดํฐ JPA (0) | 2023.01.28 |
์คํ๋ง ์ ๋ฌธ - (16) ์คํ๋ง JdbcTemplate (0) | 2023.01.27 |
์คํ๋ง ์ ๋ฌธ - (15) ์คํ๋ง ํตํฉ ํ ์คํธ (0) | 2023.01.27 |
์คํ๋ง ์ ๋ฌธ - (14) ์คํ๋ง DB ์ ๊ทผ ๊ธฐ์ / ์์ Jdbc (0) | 2023.01.26 |