스프링에서 JPA 사용 하기(스프링부트, JPA)


이번에는 스프링 프레임워크에서 JPA를 사용 하는 방법에 대해서 정리 해보겠습니다. 스프링 프레임워크 프로젝트에서 스프링 데이터 JPA를 얼마나 효율적이고 간단하게 사용이 가능 한지 기능 별로 살펴 보겠습니다.

스프링 데이터 JPA 개발 환경 구성

  1. 환경

    • Spring-boot 2.2.1.RELEASE
    • JDK 1.8
    • Maven
    • Eclipse IDE
  2. 라이브러리 설정

    • pom.xml 의존성 추가
     <!-- h2 database -->
     <dependency>
         <groupId>com.h2database</groupId>
         <artifactId>h2</artifactId>
         <scope>runtime</scope>
     </dependency>
        
     <!-- 스프링부트 데이터 JPA -->
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-data-jpa</artifactId>
     </dependency>
       
     <!-- 프로젝트 lombok (get,set 을 편리하게 만들수 있는 오픈소스 라이브러리) -->
     <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <version>1.18.10</version>
         <scope>provided</scope>
     </dependency>
    
  3. 환경 설정

    • application.properties

        spring.jpa.hibernate.ddl-auto=create
        spring.jpa.generate-ddl=false
        spring.jpa.show-sql=true
              
        spring.datasource.url=jdbc:h2:tcp://localhost/~/test
        spring.datasource.username=sa
        spring.datasource.password=1234
        spring.datasource.driverClassName=org.h2.Driver
      



스프링부트 데이터 JPA 사용하기


  1. 데이터 JPA 기본 사용 방법

    회원 엔티티를 작성 합니다.

    • 회원 엔티티

        @Data                   //lombok
        @NoArgsConstructor      //lombok
        @AllArgsConstructor     //lombok
              
        @Entity
        @Table(name = "MEMBER")
        public class Member {
                  
            @Id @GeneratedValue
            private long id;
                  
            private String name;
        }
      

    스프링 데이터 JPA는 기본 CRUD 기능을 사용 할수 있도록 JpaRepository<T, ID> 인터페이스를 제공 합니다.

    • JpaRepository 인터페이스

           public interface JpaRepository<T, ID>{} 
      

    MemberRepository 인터페이스를 생성 해서 JpaRepository 를 상속 받습니다.
    JpaRepository<T, ID>의 제네릭은 사용 하고자 하는 엔티티와 엔티티의 식별자 타입을 입력합니다.

    • MemberRepository 인터페이스

        public interface MemberRepository extends JpaRepository<Member, Long>{
        }
      

    메인 어플리케이션을 작성 합니다.

    • application 클래스

        @Slf4j
        @SpringBootApplication
        public class JpaExam8Application {
              
            public static void main(String[] args) {
                SpringApplication.run(JpaExam8Application.class, args);
            }
                  
            @Bean
            public CommandLineRunner Member(MemberRepository repository) {
                return (args) -> {
                    //엔티티 생성
                    Member member1 = new Member("홍길동");
                    Member member2 = new Member("이순신");
                    Member member3 = new Member("김철수");
                          
                    //엔티티 저장
                    repository.save(member1);
                    repository.save(member2);
                    repository.save(member3);
                          
                    //엔티티 조회
                    for(Member m : repository.findAll()) {
                        log.info("회원 명 : {}", m.getName());
                    }
            
                    //엔티티 삭제
                    repository.delete(member2);
                          
                    for(Member m : repository.findAll()) {
                        log.info("회원 명 : {}", m.getName());
                    }
                };
            }
        }
      
  2. 쿼리 메소드 기능

    쿼리 메소드 기능은 이름만으로 쿼리를 만들어 주는 스프링 데이터 JPA 의 기능입니다. MemberRepository 에 아래와 같이 이름으로 검색 하는 메소드를 작성 해보겠습니다.

    • MemberRepository

        public interface MemberRepository extends JpaRepository<Member, Long>{
            Member findMemberByName(String name);
        }
      
    • application 클래스

        @Bean
        public CommandLineRunner findMember(MemberRepository repository) {
            return (args) -> {
                Member m1 = repository.findMemberByName("홍길동");
                log.info("검색 된 회원 : {}", m1.getName());
            };
        }
      
    • 수행 결과

      테스트를 수행 하면 아래와 같이 JPQL 쿼리가 생성 되서 수행 됩니다.

        Hibernate: select member0_.member_id as member_i1_0_, member0_.member_name as member_n2_0_ from member member0_ where member0_.member_name=?
      
  3. 네임드 쿼리 사용(@NamedQuery)

    스프링데이터 JPA 에서도 아래와 같이 네임드 쿼리를 사용 할 수 있습니다.(네이티브 쿼리 동일)

    • Member 엔티티

        @Entity
        @Table(name = "MEMBER")
              
        @NamedQuery(
                name = "member.findMemberByName", 
                query = "select m from Member m where m.name = :name"
        )
              
        @Data
        @NoArgsConstructor
        public class Member {
                  
            @Id @GeneratedValue
            @Column(name= "MEMBER_ID")
            private long id;
                  
            @Column(name= "MEMBER_NAME")
            private String name;
              
            public Member(String name) {
                this.name = name;
            }
        }
      
    • MemberRepository 인터페이스

        public interface MemberRepository extends JpaRepository<Member, Long>{
            Member findMemberByName(@Param("name") String memberName);
        }
      
    • application 클래스

        @Bean
        public CommandLineRunner findMember(MemberRepository repository) {
            return (args) -> {
                Member m1 = repository.findMemberByName("홍길동");
                log.info("검색 된 회원 : {}", m1.getName());
            };
        }
      
  4. 쿼리 정의 (@Query)

    MemberRepository 인터페이스에 @Query 어노테이션을 이용 하여 쿼리를 직접 정의 할 수 있습니다.

    • MemberRepository 인터페이스

        public interface MemberRepository extends JpaRepository<Member, Long>{
            @Query("select m from Member m where m.name = :name or m.id = :id")
            Member findMemberByName(@Param("name") String memberName, @Param("id") long id);
            
            //아래와 같이 위치 기반 으로 바인딩이 가능하다.
            //@Query("select m from Member m where m.name = ?1 or m.id = ?2")
            //public Member findMemberByName(String memberName, long id);
        }
      
  5. 페이지 사용

    스프링 데이터 JPA 에서는 페이지 기능을 제공 합니다. findAll(Pageable) 메소드를 이용 하여 간단히 구현이 가능합니다.

     @Bean
     public CommandLineRunner findPageMember(MemberRepository repository) {
            
         return (args) -> {
             PageRequest pagerequest = PageRequest.of(0, 10, Sort.by(Direction.ASC, "name"));
             Page<Member> m1 = repository.findAll(pagerequest);
                
             log.info("페이지 건수 : {}", m1.getTotalPages());
             log.info("다음 페이지 존재 여부 : {}", m1.hasNext());
                
             List<Member> members = m1.getContent();
             for (Member m : members) {
                 log.info("회원 명 : {}", m.getName());
             }
         };
     }
    

마무리

JPA만 사용 했을 경우와 스프링 프레임워크 데이터 JPA 에서 사용 했을 경우를 비교 하면 비교가 안될만큼 간단한 코딩으로 JPA 사용이 가능 한 것을 확인 할 수 있습니다. JPA에 대해 전반적인 기능들을 살펴 보았기 때문에 다음에는 스프링에서 제공하는 예제를 가지고 기능을 어떻게 구현 했는지 살펴 보도록 하겠습니다.

#JPA #JPQL #hibernate #Spring #SpringBoot #Developer #JAVA #BackEnd #FrontEnd

Back to blog