๐Ÿƒ Spring Boot - โ‘ต

Jae Chanยท2023๋…„ 4์›” 5์ผ
1

SpringBoot

๋ชฉ๋ก ๋ณด๊ธฐ
2/2
post-thumbnail

๐Ÿ’ก 1์žฅ ๋ณต์Šต ์ดํ›„์˜ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

Jpa Repository ๐Ÿƒ

1์žฅ ๋ณต์Šต์—์„œ ์–ธ๊ธ‰ํ•œ Spring Data JPA๋Š” JPA์˜ ๊ตฌํ˜„์ฒด์ธ Hibernate๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•œ API๋“ค์„ ์ œ๊ณตํ•œ๋‹ค. ์ด ์ค‘ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด JpaRepository ๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.

Spring Data JPA์—์„œ๋Š” ์—ฌ๋Ÿฌ ํƒ€์ž…์˜ ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋Šฅ์„ ํ†ตํ•ด JPA ์ž‘์—…์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ด์ค€๋‹ค.

โœ… CRUD ๊ธฐ๋Šฅ
โœ… ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ
โœ… ์ •๋ ฌ ๊ธฐ๋Šฅ

์ด๋ ‡๊ฒŒ ์ข‹์€ ๊ธฐ๋Šฅ๋“ค์„ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ํ˜ธ์ถœํ•˜๋Š” ํ˜•ํƒœ๋กœ ์žˆ์œผ๋ฉฐ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์— ๋”ฐ๋ผ ์ƒ์†์œผ๋กœ ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•ด์ฃผ๊ณ  ์žˆ๋‹ค.

์ด๋ ‡๋“ฏ JpaRepository๋Š” ์ƒ์†ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์„ ์–ธ๋งŒ ํ•ด์ฃผ๋Š” ๊ฒƒ์œผ๋กœ ๊ตฌํ˜„์ด ๋๋‚œ๋‹ค.

BookRepository Interface

package springbootstudy.ch1.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import springbootstudy.ch1.entity.BookMarket;

/* JpaRepository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์† */
public interface BookRepository extends JpaRepository<BookMarket, Long> {
}

์ด์ฒ˜๋Ÿผ JpaRepository๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์—”ํ‹ฐํ‹ฐ์˜ ์ •๋ณด์™€ @Id์˜ ํƒ€์ž…์„ ์ง€์ •ํ•œ๋‹ค.
์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์Šคํ”„๋ง์ด ๋‚ด๋ถ€์ ์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์— ๋งž๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์Šคํ”„๋ง์˜ ๋นˆ(Bean)์œผ๋กœ ๋“ฑ๋ก์ด ๋œ๋‹ค!


๊ฐ„๋‹จํ•œ CRUD ๊ตฌํ˜„

์œ„์—์„œ ๊ตฌํ˜„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด SQL๋ฌธ ์—†์ด ์•„๋ž˜์˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ํ†ตํ•ด CRUD ์ž‘์—…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

  • Insert : save(Entity)
  • Select : findById(Key) , getOne(Key)
  • Update : save(Entity)
  • Delete : DeleteById(Key) , Delete(Entity)

โš ๏ธ : ์—ฌ๊ธฐ์„œ Insert์™€ Updata ์ž‘์—…์‹œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ save()๋กœ ๋™์ผํ•œ๋ฐ, ์ด๋Š” JPA ๊ตฌํ˜„์ฒด๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๊ฐ์ฒด๋ฅผ ๋น„๊ตํ•œ ํ›„ ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ Insert, ์กด์žฌํ•  ๊ฒฝ์šฐ Update๋ฅผ ๋™์ž‘์‹œํ‚ค๋Š” ๋ฐฉ์‹์ด๋‹ค.

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์ธ BookRepoTest.java

package springbootstudy.ch1.repository;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/* ํ…Œ์ŠคํŠธ ์ „์— ์˜์กด์„ฑ ์ฃผ์ž… ํ™•์ธ */
@SpringBootTest
public class BookRepoTest {

    @Autowired
    BookRepository bookRepository;

    @Test
    public void testClass() {
        // ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์˜ ์‹ค์ œ ๊ฐ์ฒด ํ™•์ธ
        System.out.println(bookRepository.getClass().getName());
    }
}

โœ… ํ…Œ์ŠคํŠธ ์ „์— BookRepository์˜ ์˜์กด์„ฑ ์ฃผ์ž…์ด ๋ฌธ์ œ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๊ฒฐ๊ณผ

ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ๋™์  ํ”„๋ก์‹œ๋ผ๋Š” ๋ฐฉ์‹์œผ๋กœ ๋งŒ๋“ค์–ด์ ธ ์ถœ๋ ฅ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


Insert ํ…Œ์ŠคํŠธ

Insert ์ž‘์—…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ œ๊ณต๋˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • save()

๋“ฑ๋ก ํ…Œ์ŠคํŠธ๋Š” ํ•œ๊บผ๋ฒˆ์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ €์žฅํ•˜๋„๋ก ์ž‘์„ฑํ•ด๋ดค๋‹ค.

package springbootstudy.ch1.repository;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import springbootstudy.ch1.entity.BookMarket;
import java.util.stream.IntStream;

@SpringBootTest
public class BookRepoTest {

    @Autowired
    BookRepository bookRepository;

    @Test
    public void testInsert() {
        IntStream.rangeClosed(1,50).forEach(i -> {
            BookMarket bookMarket = BookMarket.builder().bookName("์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : " + i).build();
            bookRepository.save(bookMarket);
        });
    }
}

testInsert() ๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€ ๋‚ด์šฉ์€, BookMarket ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๊ณ  ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์† ๋ฐ›์€ ๊ฐ์ฒด bookRepository ๋ฅผ ํ†ตํ•ด 50๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์คฌ๋‹ค.

โœ… ํ˜„์žฌ BookMarket ๊ฐ์ฒด์˜bookName์€ ์กฐ๊ฑด์ด Not Null ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜๋“œ์‹œ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค.

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‚ด๋ถ€ ํ™•์ธ ๊ฒฐ๊ณผ


SELECT ํ…Œ์ŠคํŠธ

์กฐํšŒ ์ž‘์—…์˜ ํ…Œ์ŠคํŠธ๋Š” ๋‹ค์Œ์˜ ๋ฉ”์†Œ๋“œ๋“ค์„ ํ†ตํ•ด ๊ฐ์ฒด ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • findById()
  • getOne()

์„œ๋กœ ๋™์ž‘ ๋ฐฉ์‹์ด ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅด๋‹ค.

findByID()

    @Test
    public void selectTest() {
        int bookNumber = 180; // ์ž„์‹œ ์กฐํšŒ ๋ฒˆํ˜ธ
        Optional<BookMarket> result = bookRepository.findById(bookNumber);
        System.out.println("=========== Hibernate ์ฒดํฌ ===========");
        System.out.println(result);
    }
}

findById์˜ ๊ฒฝ์šฐ Optional ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์ฒดํฌํ•˜๋Š” ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•˜๊ฒŒ ๋ผ์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ๋กœ๊ทธ๊ฐ€ ํ„ฐ๋ฏธ๋„์— ๊ธฐ๋ก๋œ๋‹ค.

๊ฒฐ๊ณผ

getOne() ๋ฉ”์†Œ๋“œ์˜ ๊ฒฝ์šฐ Transactional ์–ด๋…ธํ…Œ์ด์…˜์ด ์ถ”๊ฐ€์ ์œผ๋กœ ํ•„์š”ํ•˜๋‹ค.

getOne()

  @Transactional
    @Test
    public void selectGetOneTest() {
        int bookNumber = 190; // ์ž„์‹œ ์กฐํšŒ ๋ฒˆํ˜ธ
        BookMarket bookMarket = bookRepository.getOne(bookNumber);
        System.out.println("=========== Hibernate ์ฒดํฌ ===========");
        System.out.println(bookMarket);
    }

getOne์˜ ๊ฒฝ์šฐ ๋ฆฌํ„ด ๊ฐ’์€ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ์ฒด์ด์ง€๋งŒ, SQL์„ ๋ฐ”๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค.
์œ„์˜ ํ„ฐ๋ฏธ๋„ ๊ฒฐ๊ณผ์ฒ˜๋Ÿผ ์ถœ๋ ฅ์ด ๋จผ์ € ๋˜๊ณ  ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ˆœ๊ฐ„์— SQL๋ฌธ์ด ์‹คํ–‰๋œ๋‹ค.


UPDATE ํ…Œ์ŠคํŠธ

Update๋Š” Insert์™€ ๋™์ผํ•˜๊ฒŒ save() ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•ด ์ฒ˜๋ฆฌํ•œ๋‹ค.

๋ฉ”์†Œ๋“œ ์ž‘๋™ ์‹œ ๋‚ด๋ถ€์—์„œ๋Š” ํ•ด๋‹น Entity์˜ ๊ฐ’์ด ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ ํ›„
Insert ๋˜๋Š” Update ์ฒ˜๋ฆฌ
ํ•œ๋‹ค.

    @Test
    public void updateTest() {
        /* ๋ฉค๋ฒ„ ๋ฒˆํ˜ธ 50 ์—…๋ฐ์ดํŠธ
        *  ์ฑ… ์ด๋ฆ„ ์—…๋ฐ์ดํŠธ : ๋‚˜๋Š” ๊ณ ์–‘์ด๋กœ์†Œ์ด๋‹ค */
        BookMarket bookMarket = BookMarket.builder().memberNo(200).bookName("๋‚˜๋Š” ๊ณ ์–‘์ด๋กœ์†Œ์ด๋‹ค").build();
        System.out.println(bookRepository.save(bookMarket));
    }

๊ฒฐ๊ณผ

ํ„ฐ๋ฏธ๋„ ๋‚ด๋ถ€์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋“ฏ์ดJPA๊ฐ€ ์ง€์ •ํ•œ ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ•˜๋Š” ์ง€
Select๋กœ ๊ฒ€์ƒ‰ ํ›„ Update ๋˜๋Š” Insert ์ž‘์—…ํ•  ์ง€ ์ •ํ•œ๋‹ค.


DELETE ํ…Œ์ŠคํŠธ

์‚ญ์ œ๋˜ํ•œ ๋™์ผํ•˜๊ฒŒ ์—†์• ์•ผ ํ•  ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ•œ ์ง€ ํ™•์ธ ํ›„ ์ž‘์—…์„ ์‹คํ–‰ํ•œ๋‹ค.

  • deleteById()

์ฝ”๋“œ

    @Test
    public void deleteTest() {
        // ๋ฒˆํ˜ธ 51 - 200๋ฒˆ ๊นŒ์ง€์˜ ๋ฐ์ดํ„ฐ ์‚ญ์ œ.
        int deleteMemberNum;
        for(deleteMemberNum = 51; deleteMemberNum < 201; deleteMemberNum++) {
            bookRepository.deleteById(deleteMemberNum);
        }
    }

๊ฒฐ๊ณผ

Hibernate: 
    select
        b1_0.member_no,
        b1_0.book_name 
    from
        table_book_market b1_0 
    where
        b1_0.member_no=?
Hibernate: 
    delete 
    from
        table_book_market 
    where
        member_no=?

ํ„ฐ๋ฏธ๋„ ๋‚ด๋ถ€ ๋ชจ์Šต์ด๋‹ค. select ์ž‘์—… ํ›„ delete๊ฐ€ ์‹คํ–‰ ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฐ์ดํ„ฐ๊ฐ€ ๋ง๋”ํžˆ ์‚ฌ๋ผ์กŒ๋‹ค!


Paging ์ฒ˜๋ฆฌ

  • ํŽ˜์ด์ง•(Paging) : ๋งŽ์€ ๋ฐ์ดํ„ฐ๋“ค ์ค‘ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋“ค๋งŒ์„ ๋ณด์—ฌ์ฃผ๋Š” ์ฒ˜๋ฆฌ ๋ฐฉ์‹์ด๋‹ค.

Spring Data JPA์—์„œ๋Š” ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ ๋ฐ ์ •๋ ฌ์„ findAll() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ž‘์—…ํ•œ๋‹ค.

โš ๏ธ ์ฃผ์˜ํ•  ์‚ฌํ•ญ !

  • ๋ฉ”์†Œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์ด Pageable ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜๋“œ์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…์„ Pageable๋กœ ์ง€์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

Pageable Interface

ํŽ˜์ด์ง€ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด์„œ๋Š” Pageable ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•˜๋‹ค.

  • ์šฉ๋„ : ํŽ˜์ด์ง€ ์ฒ˜๋ฆฌ์— ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜๋Š” ํƒ€์ž…์ด๋‹ค.
  • ํŠน์ง• : ๊ฐ์ฒด ์ƒ์„ฑ์„ new ๊ฐ€ ์•„๋‹Œ static ํƒ€์ž… of() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ : org.springframework.data.domain.Page
of(int page, int size)
- 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ์™€ ๊ฐœ์ˆ˜

of(int page, int size, Sort.Direction direction, String props) 
- 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ์™€ ๊ฐœ์ˆ˜ & ์ •๋ ฌ ๋ฐฉํ–ฅ ๋ฐ ์ •๋ ฌ ๊ธฐ์ค€ ํ•„๋“œ

of(int page, int size, Sort sort)
- ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ์™€ ๊ฐœ์ˆ˜ & ์ •๋ ฌ ์ •๋ณด

์ด๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ดค๋‹ค.

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

 @Test
    public void PagingTest() {
        Pageable pageable = PageRequest.of(0,10);
        Page<BookMarket> pageResult = bookRepository.findAll(pageable);
        System.out.println("ํŽ˜์ด์ง€ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ : " + pageResult);
        System.out.println("์ด ํŽ˜์ด์ง€ ๊ฐœ์ˆ˜ : " + pageResult.getTotalPages());
        System.out.println("์ „์ฒด ๊ฐœ์ˆ˜ : " + pageResult.getTotalElements()); // ํŽ˜์ด์ง€ ์ฒ˜๋ฆฌ๋œ ๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜
        System.out.println("ํ˜„์žฌ ํŽ˜์ด์ง€์˜ ๋ฒˆํ˜ธ : " + pageResult.getNumber());
        System.out.println("ํ•œ ํŽ˜์ด์ง€์˜ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜ : " + pageResult.getSize());
        System.out.println("๋‹ค์Œ ํŽ˜์ด์ง€์˜ ์กด์žฌ ์—ฌ๋ถ€(T/F) : " + pageResult.hasNext());
        System.out.println("ํ˜„์žฌ ํŽ˜์ด์ง€์˜ ์ฒซ ๋ฒˆ์งธ ์—ฌ๋ถ€(T/F) : " + pageResult.isFirst());
    }

๊ฒฐ๊ณผ

ํŽ˜์ด์ง€ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ : Page 1 of 6 containing 
springbootstudy.ch1.entity.BookMarket instances

์ด ํŽ˜์ด์ง€ ๊ฐœ์ˆ˜ : 6
์ „์ฒด ๊ฐœ์ˆ˜ : 51
ํ˜„์žฌ ํŽ˜์ด์ง€์˜ ๋ฒˆํ˜ธ : 0
ํ•œ ํŽ˜์ด์ง€์˜ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜ : 10
๋‹ค์Œ ํŽ˜์ด์ง€์˜ ์กด์žฌ ์—ฌ๋ถ€(T/F) : true
ํ˜„์žฌ ํŽ˜์ด์ง€์˜ ์ฒซ ๋ฒˆ์งธ ์—ฌ๋ถ€(T/F) : true

ํ˜„์žฌ ๋ฐ์ดํ„ฐ๊ฐ€ 51๊ฐœ์ด๊ณ , 10๊ฐœ์˜ ๋ฐ์ดํ„ฐ์”ฉ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์—ฌ 6๊ฐœ์˜ ํŽ˜์ด์ง€๊ฐ€ ์กด์žฌํ•œ๋‹ค.
getContent() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ํŽ˜์ด์ง€ ๋‚ด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

for(BookMarket bm : pageResult.getContent()) {
	System.out.println(bm);
}
BookMarket(memberNo=202, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 202)
BookMarket(memberNo=203, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 203)
BookMarket(memberNo=204, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 204)
BookMarket(memberNo=205, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 205)
BookMarket(memberNo=206, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 206)
BookMarket(memberNo=207, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 207)
BookMarket(memberNo=208, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 208)
BookMarket(memberNo=209, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 209)
BookMarket(memberNo=210, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 210)
BookMarket(memberNo=211, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 211)

Query Methods

๐Ÿ’ก ์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ
๋ฉ”์†Œ๋“œ์˜ ์ด๋ฆ„ ์ž์ฒด๊ฐ€ ์ฟผ๋ฆฌ์˜ ๊ตฌ๋ฌธ์œผ๋กœ์„œ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ–๊ณ  ์žˆ๋Š” ๋ฉ”์†Œ๋“œ

์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ

์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ๋Š” ์‚ฌ์šฉํ•˜๋Š” ํ‚ค์›Œ๋“œ์— ๋”ฐ๋ผ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ๊ฐœ์ˆ˜๊ฐ€ ๊ฒฐ์ •๋œ๋‹ค.
ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž… ์ง€์ • ์‹œ ์ค‘์š”ํ•œ ์‚ฌํ•ญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • Select : List ํƒ€์ž…์ด๋‚˜ Array๋“ฑ์˜ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Pageable : ๋ฌด์กฐ๊ฑด Page<E> ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•ด์ค˜์•ผํ•œ๋‹ค.

ํ…Œ์ŠคํŠธ

๋จผ์ € JPARepository๋ฅผ ์ƒ์†๋ฐ›์€ ์ธํ„ฐํŽ˜์ด์Šค์— ์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

package springbootstudy.ch1.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import springbootstudy.ch1.entity.BookMarket;

import java.util.List;

public interface BookRepository extends JpaRepository<BookMarket, Integer> {
    List<BookMarket> findByMemberNoBetweenOrderByMemberNoDesc(Integer from, Integer to);
}

๋ฉ”์†Œ๋“œ ์ด๋ฆ„์˜ ๊ฐ€๋…์„ฑ์ด ๋‚ฎ์ง€๋งŒ.. ํ•ด์„ํ•ด๋ณด๋ฉด memberNo๋ฅผ ๊ธฐ์ค€์œผ๋กœ Between ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ OrderBy๋ฅผ ์ ์šฉํ•˜๊ณ  ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•œ ์งˆ์˜๋ฌธ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜์žˆ๋‹ค.

    @Test
    public void queryMethodsTest() {
        List<BookMarket> list = bookRepository.findByMemberNoBetweenOrderByMemberNoDesc(210,220);

        for(BookMarket bm : list) {
            System.out.println("์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : " + bm);
        }
    }
Hibernate: 
    select
        b1_0.member_no,
        b1_0.book_name 
    from
        table_book_market b1_0 
    where
        b1_0.member_no between ? and ? 
    order by
        b1_0.member_no desc
        
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=220, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 220)
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=219, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 219)
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=218, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 218)
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=217, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 217)
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=216, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 216)
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=215, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 215)
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=214, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 214)
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=213, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 213)
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=212, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 212)
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=211, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 211)
์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ ์ ์šฉ ๊ฒฐ๊ณผ : BookMarket(memberNo=210, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 210)

Pageable ํ™œ์šฉ

๋ฐฉ๊ธˆ๊ณผ ๊ฐ™์ด OrderBy๋“ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ์˜ ์ด๋ฆ„์ด ๊ธธ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— Pageable์„ ์ด์šฉํ•ด ์ •๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋ฉด ๊ฐ„๋‹จํ•˜๊ฒŒ ์ƒ์„ฑ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

ํ…Œ์ŠคํŠธ

Page<BookMarket> findByMemberNoBetween(Integer from, Integer to, Pageable pageable);
    @Test
    public void pageableQueryMethodsTest() {
        /* ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ */
        Pageable pageable = PageRequest.of(0,10, Sort.by("memberNo").ascending());
        Page<BookMarket> result = bookRepository.findByMemberNoBetween(240,250,pageable);
        result.get().forEach(bookMarket -> System.out.println(bookMarket));
    }

๊ฒฐ๊ณผ

Hibernate: 
    select
        count(b1_0.member_no) 
    from
        table_book_market b1_0 
    where
        b1_0.member_no between ? and ?
        
BookMarket(memberNo=240, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 240)
BookMarket(memberNo=241, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 241)
BookMarket(memberNo=242, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 242)
BookMarket(memberNo=243, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 243)
BookMarket(memberNo=244, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 244)
BookMarket(memberNo=245, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 245)
BookMarket(memberNo=246, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 246)
BookMarket(memberNo=247, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 247)
BookMarket(memberNo=248, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 248)
BookMarket(memberNo=249, bookName=์ฑ… ์ƒ˜ํ”Œ ๋ฒˆํ˜ธ : 249)

deleteBy

์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ๋ฅผ deleteBy๋กœ ์‹œ์ž‘ํ•˜์—ฌ ์ž‘์„ฑํ•˜๋ฉด ์กฐ๊ฑด์— ๋งž๋Š” ๋ฐ์ดํ„ฐ ์‚ญ์ œ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

ํ…Œ์ŠคํŠธ

public interface BookRepository extends JpaRepository<BookMarket, Integer> {
	void deleteBookMarketByMemberNoLessThan(Integer number);
}
@Commit
@Transactional
@Test
public void deleteQueryMethodsTest() {
	/* ๋ฉค๋ฒ„ ๋ฒˆํ˜ธ๊ฐ€ 230 ์ดํ•˜์ธ ๋ฐ์ดํ„ฐ ์‚ญ์ œ. */
	bookRepository.deleteBookMarketByMemberNoLessThan(230);
}

๊ฒฐ๊ณผ

  • Commit ์–ด๋…ธํ…Œ์ด์…˜ : ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ์ปค๋ฐ‹ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜
  • Transactional ์–ด๋…ธํ…Œ์ด์…˜ : select ๋ฌธ์œผ๋กœ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋“ค์„ ๊ฐ€์ ธ์˜ค๋Š” ์ž‘์—… & ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‚ญ์ œํ•˜๋Š” ์ž‘์—…์„ ๊ฐ™์ด ํ•˜๊ธฐ ์œ„ํ•œ ์–ด๋…ธํ…Œ์ด์…˜

Query ์–ด๋…ธํ…Œ์ด์…˜

๐Ÿ’ก@Query
SQL๊ณผ ์œ ์‚ฌํ•œ ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค์˜ ์ •๋ณด๋ฅผ ์ด์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ–๊ณ  ์žˆ๋Š” ์–ด๋…ธํ…Œ์ด์…˜

์ฟผ๋ฆฌ ๋ฉ”์†Œ๋“œ๋Š” ๋ณต์žกํ•œ ์กฐ๊ฑด์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๊ฒฝ์šฐ ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์ด ๊ธธ์–ด์ง€๋Š” ๋“ฑ,
๋ถˆํŽธํ•  ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์ฟผ๋ฆฌ ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฟผ๋ฆฌ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

โœ… ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์„ ๋ณ„์ ์œผ๋กœ ์ถ”์ถœ ํ•˜๋Š” ์ž‘์—… ๊ธฐ๋Šฅ
โœ… ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋งž๋Š” ์ˆœ์ˆ˜ํ•œ SQL(Native SQL) ์ž‘์„ฑ ๊ธฐ๋Šฅ
โœ… Insert , Update , Delete ์™€ ๊ฐ™์€ DML ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ

๊ฐ์ฒด์ง€ํ–ฅ ์ฟผ๋ฆฌ๋Š” ํ…Œ์ด๋ธ” ๋Œ€์‹  Entity ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜๋ฉฐ ํด๋ž˜์Šค ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•ด ์ž‘์„ฑํ•œ๋‹ค.

@Query("select m fro BookMarket m order by m.meberNo desc")
List<BookMarket> getListDesc();

ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ

์ฟผ๋ฆฌ ์–ด๋…ธํ…Œ์ด์…˜์˜ ๊ฒฝ์šฐ SQL๋ฌธ๊ณผ ์œ ์‚ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— where๋ฌธ๊ณผ ๊ฐ™์€ ํŒŒ๋ผ๋ฏธํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ์ด ๋•Œ ์ž‘์„ฑ ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • '?1' , '?2' & 1๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆœ์„œ๋ฅผ ์ด์šฉํ•œ ๋ฐฉ์‹
  • ':xxx' ์™€ ๊ฐ™์ด ':ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„'์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹
  • :#{} ์„ ์ด์šฉํ•˜๋Š” ์ž๋ฐ” ๋นˆ ์Šคํƒ€์ผ์˜ ์ž‘์„ฑ ๋ฐฉ์‹

๋‘ ๋ฒˆ์งธ ๋ฐฉ์‹์„ ์ด์šฉํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•œ๋‹ค.

@Transactional
@Modifying
@Query("update BookMarket m set m.bookName = :bookName where m.memberNo = :memberNo")
int updateBookName(@Param("memberNo") int memberNo, @Param("bookName") String bookName);

์—ฌ๊ธฐ์„œ ํŒŒ๋ผ๋ฏธํ„ฐ ์ „๋‹ฌ์„ ์—ฌ๋Ÿฌ ๊ฐœ ํ•ด์•ผํ•œ๋‹ค๋ฉด :# ์„ ์ด์šฉํ•ด ๊ฐ์ฒด ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด ์ž์ฒด๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

@Transactional
@Modifying
@Query("update BookMarket m set m.bookName = :#{#param.bookName} where m.memberNo = :#{#param.memberNo}")
int updateBookName(@Param("param") BookMarket bookMarket); // ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด ์ž์ฒด๋กœ ์ ์šฉํ•œ๋‹ค.

Native SQL

๐Ÿ’ก Native SQL์€ ์ฟผ๋ฆฌ ์–ด๋…ธํ…Œ์ด์…˜์˜ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์ค‘ ํ•˜๋‚˜๋‹ค.
๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์˜ SQL ๊ตฌ๋ฌธ์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

/* Native SQL */
@Query(value = "select * from BookMarket where memberNo > 50" , nativeQuery = true)
List<Object[]> nativeSQLSelect();

๋งˆ์น˜๋ฉฐ

์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ข‹์•„ํ• ๋งŒํ•œ ์š”์†Œ๋Š” ๋‹ค ๋„ฃ์€๋“ฏ ํ•˜๋‹ค! ๐Ÿค”
ํŠนํžˆ ๊ท€์ฐฎ๊ฒŒ ์™”๋‹ค๊ฐ”๋‹ค ํ•  ์ผ ์—†์ด ์Šคํ”„๋ง ๋ถ€ํŠธ ๋‚ด๋ถ€์—์„œ๋„ DB ์ปจํŠธ๋กค์ด ๊ฐ€๋Šฅํ•œ๊ฒŒ ํฐ ์žฅ์ ์ด๋‹ค.

  • ์ฐธ๊ณ  ๋‚ด์šฉ
    ๐Ÿ“– ์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ ์›นํ”„๋กœ์ ํŠธ
profile
๐Ÿ‹

0๊ฐœ์˜ ๋Œ“๊ธ€