ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] JPA 설정 및 사용
    Spring 2021. 10. 11. 15:53

    jpa를 쓰기에 앞서 몇가지 설정이 필요하다.

     

    build.gradle 파일의 디펜던시에서 첫번째줄을 삽입해줘야한다.

     

    spring boot starter data jpa는 jdbc관련 라이브러리를 포함한다.

     

     

    resources/application.properties 파일에도 수정할 것이 있다.

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

    이 두 줄을 넣어줘야 하는데, 첫째 줄의 의미는 jpa로 날린걸 sql로 볼 수 있게 해준다.

    둘째 줄은 원래 jpa를 쓰면 객체를 보고 테이블까지 만들어 버린다.

    그래서 이미 만들어놨거나 그 기능이 필요없는 경우 none으로 끄고 시작하면 된다.

     

    JPA를 통한 모든 데이터 변경은 트랜잭션 안에서 실행해야 한다.

    때문에 서비스 클래스에 @Transactional을 붙여 런타임에러가 나면 롤백을, 정상 종료되면 커밋을 할 수 있도록 한다.

    JPA 사용을 위한 매핑작업

    jpa는 관계형 데이터베이스와 객체를 매핑하기 위해 몇가지 작업이 필요하다.

     

    import javax.persistence.*;
    
    @Entity
    public class Member {
    
        @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    //    @Column(name = "username")
        private String name;
    }

    맵핑을 위해 @Entitiy 어노테이션을 해줘야한다.

     

    각 멤버변수마다 테이블에서 어떤 칼럼인지를 맵핑해줘야한다.

     

    특정 멤버변수가 pk값일 경우 @id를 써 설정을 해준다.

     

    또한 pk값이 자동으로 마지막 pk값에서 +1을 해주는 식이라면

     

    @GeneratedValue(strategy = GenerationType.IDENTITY)로 지정해준다.

     

     

    JPA를 이용한 레퍼지토리 클래스 만들기

     

    package hello.hellospring.repository;
    
    import hello.hellospring.domain.Member;
    import org.springframework.expression.spel.ast.OpInc;
    
    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;
        }
    
        @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> result = em.createQuery("select m from Member m where m.name = :name", Member.class)
                    .setParameter("name", name)
                    .getResultList();
            return result.stream().findAny();
        }
    
        @Override
        public List<Member> findAll() {
            List<Member> result = em.createQuery("select m from Member m", Member.class)
                    .getResultList();
            return result;
        }
    }

    JPA는 entity manager로 모든 동작을 한다.

     

    그래서 스프링 부트는 jpa 라이브러리를 받으면 자동으로 entity manager를 자동으로 생성해준다.

     

    때문에 개발자는 인젝션만 해주면 된다.

     

    Insert

    @Override
        public Member save(Member member) {
            em.persist(member);
            return member;
        }

    entity manager의 persist함수를 써 매개변수로 그대로 넣어주기만 하면 된다.

     

     

    Search

    @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> result = em.createQuery("select m from Member m where m.name = :name", Member.class)
                    .setParameter("name", name)
                    .getResultList();
            return result.stream().findAny();
        }
    
        @Override
        public List<Member> findAll() {
            List<Member> result = em.createQuery("select m from Member m", Member.class)
                    .getResultList();
            return result;
        }

    search는 상황마다 방법이 다르다.

     

    PK로 찾기

    pk값으로 값을 찾으면 간단하다.

     

    @Override
        public Optional<Member> findById(long id) {
            Member member = em.find(Member.class, id);
            return Optional.ofNullable(member);
        }

    멤버클래스의 정보를 넣고, 찾는 키값을 넣는 find함수를 쓰면 리턴을 클래스형식으로 해준다.

     

    pk값이 아닌 column으로 찾기

    	@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();
        }
    
        @Override
        public List<Member> findAll() {
            List<Member> result = em.createQuery("select m from Member m", Member.class)
                    .getResultList();
            return result;
        }

    createQuery함수를 써 쿼리를 쓰긴해야한다. 하지만 그냥 쿼리는 아니고 jpql이라는 객체지향쿼리를 써야한다.

     

    select *을 하는 식의 쿼리가 아닌 Member entity 자체를 조회하는 식이라고 보면 된다.

     

    그렇게 조회해서 리스트로 뽑아낼 경우 getResultList()함수를 써 그대로 리턴을 하면 된다.

     

    그리고 리스트로 전부 뽑아내는게 아닌 하나의 정보값을 가져오는 함수라면

     

    where을 써 Member entity의 name과 비교할 변수를 쓰고, setParameter를 통해 해당 변수에 값을 할당해서 다시 값을 받아오면 된다.

     

     

     

    SpringConfig 설정

     

    @Configuration
    public class SpringConfig {
    
        @PersistenceContext
        private EntityManager em;
    
        @Autowired
        public SpringConfig(EntityManager em) {
            this.em = em;
        }
        @Bean
        public MemberService memberService() {
            return new MemberService(memoryRepository());
        }
    
        @Bean
        public MemberRepository memoryRepository() {
            return new JpaMemberRepository(em);
        }

    entity manager를 받아와 할당해주고, 그걸 다시 레포지토리 클래스로 보내주면 된다.

    댓글

Designed by Tistory.