주노 님의 블로그

[Spirng] 7. Spring 데이터베이스 연동 - JPA 본문

공부/Spring

[Spirng] 7. Spring 데이터베이스 연동 - JPA

juno0432 2024. 7. 29. 23:29

시작하기에 앞서

아래 내용은 김영한님의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB접근기술에서 발췌한 내용입니다.

 

 

강의자료 일부를 발췌하는건 괜찮다고 하셨다.

무료강의로 지식을 공유해주신 김영한님께 다시한번 감사의 인사를 올리겠습니다

(_ _) (유료도 샀어요!)

 

jdbc에서 jdbctmeplate로 바꾸었을때 반복되는 코드가 확 줄었다

하지만, sql은 개발자가 직접 구현해야 했었다

jpa를 사용하면 jpa가 SQL을 자동으로 생성해준다.

>> JPA를 사용하면 CRUD쿼리가 자동 실행되며 추가적인 쿼리도 간편하게 실행 가능

 

jpa를 사용하면 객체 중심으로 설계로 패러다임 전환이 가능하다.

왜! 그럴까

기존의 객체지향 언어로 자바에서 구현을 해도 RDB자체가 객체지향을 지원하지 않는다

위 내용이 간략하게 기존 jdbc를 사용할때의 문제점 이라고 할 수 있다.

 

실제로 SQL에 의존적인 개발(jdbc, jdbcTemplate 등)은 진정한 의미의 계충분할이 어려울뿐더러, SQL작성에 시간을 낭비하게 된다.

 

jpa의 기능

저장 기능 : jpa.persist(member);

조회 기능

String memberId = "helloId";

Member member = jpa.find(Member.class,memberId)

수정기능

Member member = jpa.find(Member.class, memberId);

member.setName("바꿀 이름");

연관된 객체 조회

Member member = jpa.find(Member.class, memberId);

Team team = member.getTeam();

 

으로 아주 간편해진것을 볼 수 있다.

 

일단 실습으로 들어가서

1. build.gradle 설정 추가

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

build.gradle에 위와 같은 dependencie를 추가해준다

 

2.application.properties 설정 추가

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

 

 

3. Domain에 Entity 어노테이션 추가

@Entity
public class Member {
    //아이덴티티 전략
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

도메인에 엔티티 어노테이션을 추가해야한다.

이제 jpa가 도메인을 관리한다.

 

그다음 pk를 설정해준다.

기존에 id는 db가 자동으로 생성해주고 있었다

위 strategy = GenerationType.IDENTITY 가 자동으로 DB에서 ID를 생성해준다는뜻이다

 

4. JPARepository 생성

 

public class JpaMemberRepository implements MemberRepository {

    //jpa는 entity manager로 모든게 작동된다.
    //스프링 부트가 자동으로 엔터티 매니저를 생성해준다
    private EntityManager em;
    
        //의존성 주입!
    public JpaMemberRepository(EntityManager em) {
        this.em = em;
    }

 

build gradle에서 jpa라이브러리를 불러왔기때문에

스프링에서 자동으로 entityManager을 생성해준다.

 

그리고 의존성 주입.

 

5. 저장기능 - jpa.persist(member)

public Member save(Member member) {
    //jpa가 insert 쿼리를 만들어서 집어넣는다.
    em.persist(member);
    return member;
}

 

persist : 영속한다, 영원히 존재한다.

persist를 쓰면 자동으로 jpa가 insert쿼리를 생성해서 db에 던진다

 

6. 조회기능 - jpa.find(Member.class,id)

@Override
public Optional<Member> findById(Long id) {

    Member member = em.find(Member.class, id);
    return Optional.ofNullable(member);
}

find를 사용하면 조회가 가능하다

 

7. 조회기능 - jpql사용

@Override
public List<Member> findAll() {
    //jpa는 객체를 통해 쿼리를 날린다
    //select m은 멤버 엔티티를 날린다.??
    return em.createQuery("select m from Member m", Member.class)
            .getResultList();
}

 

보이는 쿼리문이 jpql인데 원래 테이블을 대상으로 쿼리를 날리는 기존 방식과 달리

jpa는 객체를 대상으로 쿼리를 날린다 (여기서는 멤버 엔티티)

select *이 들어가거나 특정 대상이 들어가야하는데 지금은 alias만 들어간 것을 볼 수 있다

Member.class를 정의해줬기때문에 member객체를 찾는다고 볼 수 있다

 

@Override
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();
}

위 코드를 보면 select절에서 멤버를 대상으로 찾는데

데이터 베이스의 name을 입력받은 값과 동일한 것을 찾은뒤

결과값을 반환해준다.

 

어떨때 jpql을 써야할까

단건을 가지고 조회할때 : jpa문법

리스트를 가지고 조회해야할때 : jpql

 

8. 트랜젝션 어노테이션

@Transactional
public class MemberService

 

데이터를 저장할때나, 삭제할때 transaction이 필요하다.

jpa는 데이터 변경이 하나의 트랜젝션 안에서 실행되어야 한다.

 

 9.Spring config 설정

 EntityManager em;

    @Autowired
    public SpringConfig(EntityManager em) {
        this.em = em;
    }
    
    @Bean
    public MemberRepository memberRepository()
    {
//        return new MemoryMemberRepository();
//        return new JdbcMemberRepository(dataSource);
//        return new JdbcTemplateMemberRepository(dataSource);
        return new JpaMemberRepository(em);
    }

 

엔터티 메니저를 받아야한다!

 

10. 통합테스트 실행

전 강의에서 만든 코드로 통합테스트를 수행한다

persist만 작성해도 insert 쿼리가 날라가는것을 볼 수 있다.