상세 컨텐츠

본문 제목

[Spring] JPA Example (JpaRepository)

Spring/JPA

by Chan.94 2023. 3. 30. 00:01

본문

반응형

JPA에 대한 개념은 ORM, JPA에 대한 이해에 정리하였으니 참고바란다.

 

이번 글에서는 JpaRepository를 사용하는 간단한 예제에 대해 정리하였다. JPA의 가장 중요한 키워드는 영속성이다.

JPA를 처음 사용하는데 JpaRepository에 대해 공부하고있다면 영속성에 대해 먼저 공부하는 것을 추천한다.

영속성에 대한 내용은 다음 포스팅을 참고하길 바란다.

 

JPA 영속성 컨텍스트 이해 (Persistence Context)


Maven

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>
  • H2
    인메모리 관계형 데이터베이스
    메모리에서 실행되기 때문에 애플리케이션을 재시작할 때마다 초기화된다는 점에서 테스트 용도로 많이 사용한다.
  • lombox
    lombok에 대해 모른다면 lombok 어노테이션에 대해 먼저 학습하길 권장한다.

 

application.properties

spring.jpa.properties.hibernate.show_sql=true

 

Entity

@Getter
@NoArgsConstructor
@Entity
public class Posts {
	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 500, nullable = false)
    private String title;

    @Column(columnDefinition = "TEXT", nullable = false)
    private String content;

    private String author;

    @Builder
    public Posts(String title, String content, String author) {
        this.title = title;
        this.content = content;
        this.author = author;
    }
}

JPA는 lombok을 사용하는 것이 일반적이다. - lombok 어노테이션

  • @Entity
    - 테이블과 매핑될 클래스임을 나타낸다.
    - 기본값으로 클래스의 카멜케이스 이름을 스네이크 네이밍으로 되어있는 테이블 이름과 매칭한다.
      ex) SalesManager => sales_manager
  • @Id
    - 해당 테이블의 PK 필드를 나타낸다.

  • @GeneratedValue
    - PK의 생성규칙을 나타낸다.
    - 직접 ID를 생성하여 넣어 줄 것이라면 사용하지 않아도 된다.

  • @Column
    - 테이블의 컬럼을 나타내며 굳이 선언하지 않더라도 해당 클래스의 필드는 모두 컬럼이 된다.
    - 기본값 외에 추가로 변경이 필요한 옵션이 있으면 사용한다.
      문자열의 경우 VARCHAR(255)가 기본값인데, 사이즈를 500으로 늘리고 싶거나, 타입을 TEXT로 변경하고 싶을 때 사용할 수 있다.

 

Repository

public interface PostsRepository extends JpaRepository<Posts, Long>{

	List<Posts> findByContent(String content);
	List<Posts> findByIdLessThan(long id);
	List<Posts> findByIdLessThanEqual(long id);
	List<Posts> findByTitleStartingWith(String title);
}

JpaRepository를 상속받는 인터페이스를 구현한다. JpaRepository는 Spring Data JPA에서 제공하는 JPA 구현을 위한 인터페이스로 간단하게 상속하여 사전에 정의된 여러 메서드를 통해 간단히 CRUD를 수행할 수 있다. 또한 정해진 규칙과 단어를 조합한 이름으로 메서드명을 작성하는 것만으로 다양한 쿼리를 생성할 수 있다.

 

Spring Data JPA 에서 정해놓은 네이밍 컨벤션을 지키면 JPA가 해당 메서드 이름을 분석해서 적절한 SQL을 작성한다.

자세한 내용은 공식문서에 설명되어있다. - Spring Data JPA 공식 문서

 

Junit Test

@Slf4j
@SpringBootTest
class JpaApplicationTests {

    @Autowired
    PostsRepository postsRepository;

    @After(value = "execution(* com.jpa.example.*(..))")
    public void cleanup() {
        postsRepository.deleteAll();
    }

    @Test
    public void boardList() {
        String title = "테스트 게시글";
        String content = "";

        /*init data*/
        for(int cnt = 1 ; cnt <= 10 ; cnt++) {
        	content = (cnt % 2 == 0 ? "짝": "홀");
        	
        	postsRepository.save(Posts.builder()
        			.title(title)
        			.content(content)
        			.author("devlog" + cnt)
        			.build());
        	
        }

        List<Posts> postsList = postsRepository.findAll();
        printList(postsList, "findAll");
        
        postsList = postsRepository.findByContent("짝");
        printList(postsList, "findByContent - 짝");
        
        postsList = postsRepository.findByContent("홀");
        printList(postsList, "findByContent - 홀");
        
        postsList = postsRepository.findByIdLessThan(5);
        printList(postsList, "findByIdLessThen");
        
        postsList = postsRepository.findByIdLessThanEqual(5);
        printList(postsList, "findByIdLessThanEqual");
        
        postsList = postsRepository.findByTitleStartingWith("테스트");
        printList(postsList, "findByTitleLike");
        
    }

    private void printList(List<Posts> postsList, String logName) {
    	log.info("=========================[{} START]=========================", logName);
        for(Posts posts : postsList) {
        	log.info("id : {}, title : {}, contents : {}, author : {}", posts.getId(), posts.getTitle(), posts.getContent(), posts.getAuthor());
        }
    	log.info("=========================[{} END]=========================\n", logName);
    }
}

log

Hibernate: drop table if exists posts CASCADE 
Hibernate: create table posts (id bigint generated by default as identity, author varchar(255), content TEXT not null, title varchar(500) not null, primary key (id))
2023-03-29 17:51:54.953  INFO 23236 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2023-03-29 17:51:54.990  INFO 23236 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2023-03-29 17:51:56.800  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : Started JpaApplicationTests in 10.686 seconds (JVM running for 14.079)
Hibernate: insert into posts (id, author, content, title) values (default, ?, ?, ?)
Hibernate: insert into posts (id, author, content, title) values (default, ?, ?, ?)
Hibernate: insert into posts (id, author, content, title) values (default, ?, ?, ?)
Hibernate: insert into posts (id, author, content, title) values (default, ?, ?, ?)
Hibernate: insert into posts (id, author, content, title) values (default, ?, ?, ?)
Hibernate: insert into posts (id, author, content, title) values (default, ?, ?, ?)
Hibernate: insert into posts (id, author, content, title) values (default, ?, ?, ?)
Hibernate: insert into posts (id, author, content, title) values (default, ?, ?, ?)
Hibernate: insert into posts (id, author, content, title) values (default, ?, ?, ?)
Hibernate: insert into posts (id, author, content, title) values (default, ?, ?, ?)
Hibernate: select posts0_.id as id1_0_, posts0_.author as author2_0_, posts0_.content as content3_0_, posts0_.title as title4_0_ from posts posts0_
2023-03-29 17:51:57.643  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findAll START]=========================
2023-03-29 17:51:57.643  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 1, title : 테스트 게시글, contents : 홀, author : devlog1
2023-03-29 17:51:57.644  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 2, title : 테스트 게시글, contents : 짝, author : devlog2
2023-03-29 17:51:57.645  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 3, title : 테스트 게시글, contents : 홀, author : devlog3
2023-03-29 17:51:57.645  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 4, title : 테스트 게시글, contents : 짝, author : devlog4
2023-03-29 17:51:57.645  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 5, title : 테스트 게시글, contents : 홀, author : devlog5
2023-03-29 17:51:57.648  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 6, title : 테스트 게시글, contents : 짝, author : devlog6
2023-03-29 17:51:57.648  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 7, title : 테스트 게시글, contents : 홀, author : devlog7
2023-03-29 17:51:57.648  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 8, title : 테스트 게시글, contents : 짝, author : devlog8
2023-03-29 17:51:57.649  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 9, title : 테스트 게시글, contents : 홀, author : devlog9
2023-03-29 17:51:57.650  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 10, title : 테스트 게시글, contents : 짝, author : devlog10
2023-03-29 17:51:57.651  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findAll END]=========================

Hibernate: select posts0_.id as id1_0_, posts0_.author as author2_0_, posts0_.content as content3_0_, posts0_.title as title4_0_ from posts posts0_ where posts0_.content=?
2023-03-29 17:51:57.769  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findByContent - 짝 START]=========================
2023-03-29 17:51:57.769  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 2, title : 테스트 게시글, contents : 짝, author : devlog2
2023-03-29 17:51:57.770  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 4, title : 테스트 게시글, contents : 짝, author : devlog4
2023-03-29 17:51:57.770  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 6, title : 테스트 게시글, contents : 짝, author : devlog6
2023-03-29 17:51:57.770  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 8, title : 테스트 게시글, contents : 짝, author : devlog8
2023-03-29 17:51:57.770  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 10, title : 테스트 게시글, contents : 짝, author : devlog10
2023-03-29 17:51:57.770  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findByContent - 짝 END]=========================

Hibernate: select posts0_.id as id1_0_, posts0_.author as author2_0_, posts0_.content as content3_0_, posts0_.title as title4_0_ from posts posts0_ where posts0_.content=?
2023-03-29 17:51:57.772  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findByContent - 홀 START]=========================
2023-03-29 17:51:57.772  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 1, title : 테스트 게시글, contents : 홀, author : devlog1
2023-03-29 17:51:57.772  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 3, title : 테스트 게시글, contents : 홀, author : devlog3
2023-03-29 17:51:57.773  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 5, title : 테스트 게시글, contents : 홀, author : devlog5
2023-03-29 17:51:57.773  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 7, title : 테스트 게시글, contents : 홀, author : devlog7
2023-03-29 17:51:57.773  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 9, title : 테스트 게시글, contents : 홀, author : devlog9
2023-03-29 17:51:57.773  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findByContent - 홀 END]=========================

Hibernate: select posts0_.id as id1_0_, posts0_.author as author2_0_, posts0_.content as content3_0_, posts0_.title as title4_0_ from posts posts0_ where posts0_.id<?
2023-03-29 17:51:57.793  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findByIdLessThen START]=========================
2023-03-29 17:51:57.794  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 1, title : 테스트 게시글, contents : 홀, author : devlog1
2023-03-29 17:51:57.794  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 2, title : 테스트 게시글, contents : 짝, author : devlog2
2023-03-29 17:51:57.795  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 3, title : 테스트 게시글, contents : 홀, author : devlog3
2023-03-29 17:51:57.795  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 4, title : 테스트 게시글, contents : 짝, author : devlog4
2023-03-29 17:51:57.795  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findByIdLessThen END]=========================

Hibernate: select posts0_.id as id1_0_, posts0_.author as author2_0_, posts0_.content as content3_0_, posts0_.title as title4_0_ from posts posts0_ where posts0_.id<=?
2023-03-29 17:51:57.802  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findByIdLessThanEqual START]=========================
2023-03-29 17:51:57.802  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 1, title : 테스트 게시글, contents : 홀, author : devlog1
2023-03-29 17:51:57.803  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 2, title : 테스트 게시글, contents : 짝, author : devlog2
2023-03-29 17:51:57.803  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 3, title : 테스트 게시글, contents : 홀, author : devlog3
2023-03-29 17:51:57.803  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 4, title : 테스트 게시글, contents : 짝, author : devlog4
2023-03-29 17:51:57.803  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 5, title : 테스트 게시글, contents : 홀, author : devlog5
2023-03-29 17:51:57.803  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findByIdLessThanEqual END]=========================

Hibernate: select posts0_.id as id1_0_, posts0_.author as author2_0_, posts0_.content as content3_0_, posts0_.title as title4_0_ from posts posts0_ where posts0_.title like ? escape ?
2023-03-29 17:51:57.830  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findByTitleLike START]=========================
2023-03-29 17:51:57.830  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 1, title : 테스트 게시글, contents : 홀, author : devlog1
2023-03-29 17:51:57.830  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 2, title : 테스트 게시글, contents : 짝, author : devlog2
2023-03-29 17:51:57.831  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 3, title : 테스트 게시글, contents : 홀, author : devlog3
2023-03-29 17:51:57.831  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 4, title : 테스트 게시글, contents : 짝, author : devlog4
2023-03-29 17:51:57.831  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 5, title : 테스트 게시글, contents : 홀, author : devlog5
2023-03-29 17:51:57.831  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 6, title : 테스트 게시글, contents : 짝, author : devlog6
2023-03-29 17:51:57.835  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 7, title : 테스트 게시글, contents : 홀, author : devlog7
2023-03-29 17:51:57.836  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 8, title : 테스트 게시글, contents : 짝, author : devlog8
2023-03-29 17:51:57.837  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 9, title : 테스트 게시글, contents : 홀, author : devlog9
2023-03-29 17:51:57.837  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : id : 10, title : 테스트 게시글, contents : 짝, author : devlog10
2023-03-29 17:51:57.837  INFO 23236 --- [           main] com.jpa.example.JpaApplicationTests      : =========================[findByTitleLike END]=========================

 

반응형

'Spring > JPA' 카테고리의 다른 글

JPA Auditing 구현 (Custom EntityListener 적용)  (1) 2024.08.28
JPA 영속성 컨텍스트 이해 (Persistence Context)  (14) 2024.08.26
ORM, JPA에 대한 이해  (12) 2023.03.29

관련글 더보기

댓글 영역

>