본문 바로가기

(10.20) Spring Boot - Spring Data JDBC, 기존 DAO 패턴 활용, repository 패턴 활용

@starweb2025. 10. 20. 20:11

[ 10주차 - 1020 ] 

    금일 커리큘럼
        ├ 09:00 ~ 12:00 backend 프로그래밍 (Spring Data JDBC, 기존 DAO 패턴 활용)
        └ 13:00 ~ 18:00 backend 프로그래밍 (repository 패턴 활용)

1. Spring Data JDBC

스프링에서 JDBC를 더 쉽게 사용할 수 있도록 도와주는 모듈

  • 객체-관계 매핑(ORM)과는 다르게, 단순한 CRUD(Create, Read, Update, Delete) 작업에 초점을 맞추고 있음.
  • SQL 쿼리를 직접 작성하지 않고도 데이터베이스 작업을 수행할 수 있도록 도와줌.
  • 복잡한 매핑이나 관계 설정이 필요하지 않은 간단한 애플리케이션에 적합함.

 

스프링 데이터 JDBC의 주요 기능

  • 리포지토리 지원: CRUD 작업을 위한 기본적인 메서드를 제공하는 리포지토리 인터페이스를 자동으로 생성.
    • 장점 : 쿼리문 작성 없이도 데이터베이스 작업 가능
    • 관련 어노테이션: CrudRepository, PagingAndSortingRepository
  • 트랜잭션 관리: 스프링의 트랜잭션 관리 기능과 통합되어 데이터 일관성을 보장.
  • 매핑: 도메인 객체와 데이터베이스 테이블 간의 매핑을 지원.

 

스프링 데이터 JDBC vs 기존 JDBC

구분 기존 JDBC 스프링 데이터 JDBC
코드 복잡도 연결, 쿼리, 반복문 등 복잡한 코드 필요 간결한 코드 작성 가능
트랜잭션 관리 수동 관리 자동 관리
객체 매핑 수동 매핑 자동 매핑 지원
예외처리 수동 처리 스프링 예외 변환 지원

 

코드량 차이점

  • 기존 JDBC는 커넥션, 쿼리 작성, 결과 처리 등 많은 보일러플레이트 코드가 필요.
  • 스프링 데이터 JDBC는 JdbcTemplate과 같은 유틸리티를 사용하여 코드량을 크게 줄일 수 있음.
// 기존 JDBC 코드 예시
public UserDAOImpl Implements UserDAO {
    private final DataSource dataSource;

    public UserDAOImpl(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public List<User> findAll() {
        List<User> users = new ArrayList<>();
        String sql = "SELECT * FROM users";

        try (Connection conn = dataSource.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql);
             ResultSet rs = ps.executeQuery()) {

            while (rs.next()) {
                User user = new User();
                user.setId(rs.getLong("id"));
                user.setName(rs.getString("name"));
                users.add(user);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }

        return users;
    }
}
// -------------------------------------------------

// 스프링 데이터 JDBC 코드 예시
@Repository
@RequiredArgsConstructor // final 붙은 필드를 생성자 자동 DI 주입 생성
public class UserDAOImpl Implements UserDAO {
    private final JdbcTemplate jdbcTemplate;

    @Override
    public List<User> findAll(User user) {
        String sql = "SELECT * FROM users";
        // BeanPropertyRowMapper 로 컬럼명 <-> 필드 자동 매핑
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));

    }
}

2. 스프링 데이터 JDBC 시작

프로젝트 생성

  • 필수 플러그인
    • Spring Web
    • Spring Data JDBC
    • MySQL Driver
    • Lombok

의존성 추가

  • build.gradle
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-jdbc' // 해당
    implementation 'com.mysql:mysql-connector-j' // 해당
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

데이터베이스 설정 (yml)

spring:
  application:
    name: library-app

  datasource:
    url: jdbc:mysql://localhost:3306/librarydb
    username: root
    password: your_password
    driver-class-name: com.mysql.cj.jdbc.Driver

# SQL 로그 출력 (학습용)
logging:
  level:
    org.springframework.jdbc: DEBUG

3. 스프링 데이터 JDBC - 기존 DAO 방식 확인

 

주요 클래스 및 어노테이션

  • JdbcTemplate : 스프링에서 제공하는 JDBC 작업을 간소화하는 유틸리티 클래스.
  • @BeanPropertyRowMapper : JDBC 결과 집합의 각 행을 도메인 객체에 매핑하는 데 사용되는 클래스.
    • 필드 <-> 컬럼 자동 매핑 지원
    • 컬럼에 (_) 있는 경우도 자동 대문자 매핑 지원 (예: user_name -> userName)
  • @RequiredArgsConstructor : Lombok 어노테이션으로, final 필드에 대한 생성자를 자동으로 생성.

 

UserDAO 쿼리 예시

@Repository
@RequiredArgsConstructor // final 붙은 필드를 생성자 자동 DI 주입 생성 (Lombok)
public class UserDAOImpl Implements UserDAO {
    private final JdbcTemplate jdbcTmpl;

    @Override
    // select All
    public List<User> findAll() {
        String sql = "SELECT * FROM users";
        // BeanPropertyRowMapper 로 컬럼명 <-> 필드 자동 매핑
        // return jdbcTmpl.query(sql, new BeanPropertyRowMapper<>(User.class));

        /* 만약 필드(userName) 컬럼(name) 매핑이 다를 경우 
        * 수동 매핑 처리 방식
        */ 
        return jdbcTmpl.query(sql, (rs, rowNum) -> {
            User user = new User();
            user.setId(rs.getLong("id"));
            user.setName(rs.getString("name")); // 컬럼명이 다를 경우 수동 매핑
            user.setEmail(rs.getString("email"));
            return user;
        });
    }

    @Override
    // select By Id
    public User findById(Long id) {
        String sql = "SELECT * FROM users WHERE id = ?";
        return jdbcTmpl.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), id);
    }

    @Override
    // insert
    public int save(User user) {
        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
        return jdbcTmpl.update(sql, user.getName(), user.getEmail());
    }

    @Override
    // update
    public int update(User user) {
        String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";
        return jdbcTmpl.update(sql, user.getName(), user.getEmail(), user.getId());
    }

    @Override
    // delete
    public int deleteById(Long id) {
        String sql = "DELETE FROM users WHERE id = ?";
        return jdbcTmpl.update(sql, id);
    }
}

4. 스프링 데이터 JDBC - 레파지토리 패턴

스프링 데이터 JDBC에서 제공하는 레파지토리 인터페이스를 사용하여 DAO 구현을 간소화할 수 있음.

  • JDBC 흐름에서 데이터 JDBC 가 담당하는 부분
Controller (웹 요청 처리)
    ↓
Service (비즈니스 로직 처리)
    ↓
Repository (데이터 액세스 처리) # <- 여기서 스프링 데이터 JDBC 제공
    ↓
Database (데이터베이스)    

 

CrudRepository 사용

CRUD 작업을 위한 메서드를 포함된 인터페이스

1) 기존 객체 클래스 로직 수정 필요

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Table("users") // 테이블명 매핑
public class User {
    @Id // PK 매핑 <- 필수
    private Long id;
    private String name;
    private String email;

    @CreatedDate             // 감사(Auditing)로 자동 세팅 (insert 시)
    @Column("created_at")    // 컬럼명 매핑
    private LocalDateTime createdAt;

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }
}

2) UserRepository 생성

@Repository
public interface UserRepository extends CrudRepository<User, Long> {
    // 메소드 구현 없이 선언만 하면 자동으로 쿼리 생성됨

    // 별도 쿼리메서드 추가 가능
    Optional<User> findByName(String name);
    Optional<User> findByEmail(String email);
}
메서드 이름 패턴 생성되는 SQL 예시
findBy{필드명} WHERE 절 추가 findByName
findBy{필드1}And{필드2} AND 조건 findByNameAndEmail
findBy{필드1}Or{필드2} OR 조건 findByNameOrEmail
findBy{필드}Like LIKE 검색 findByNameLike
findBy{필드}Containing LIKE '%keyword%' findByNameContaining
findBy{필드}StartingWith LIKE 'keyword%' findByNameStartingWith
findBy{필드}EndingWith LIKE '%keyword' findByNameEndingWith

3) 메인에서 테스트

  • CrudRepository 주요 메서드
    • save(S entity) : 엔티티 저장 (insert / update)
    • findById(ID id) : ID로 엔티티 조회
    • findAll() : 모든 엔티티 조회
    • deleteById(ID id) : ID로 엔티티 삭제
    • count() : 엔티티 개수 조회
    • existsById(ID id) : ID 존재 여부 확인
@SpringBootApplication
@EnableJdbcAuditing // 감사 활성화
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }

    @Bean
    public CommandLineRunner commandLineRunner(UserRepository repo) {
        return args -> {
            final String email = "John@John.com";

            // 1) insert
            // User addUser = repo.save(new User("John", "John@John.com"));
            User addUser = repo.findByEmail(email)
                    .orElseGet(() -> repo.save(new User("John", email)));
            System.out.println("추가됨 id=" + addUser.getId());

            // 2) update
            addUser.setName("John22");
            addUser = repo.save(addUser);
            System.out.println("업데이트(name) -> " + addUser);

            addUser.setEmail("John22@exam.com");
            addUser = repo.save(addUser);
            System.out.println("업데이트(email) -> " + addUser);

            // 3) findAll
            //  repository.findAll().forEach(System.out::println);
            Iterable<User> iterable = repo.findAll();
            List<User> userLists = new ArrayList<>();
            iterable.forEach(userLists::add);
            System.out.println(userLists);

            // 4) findById
            User userById = repo.findById(addUser.getId()).orElse(null);
            System.out.println(userById);

            // delete
            repo.deleteById(addUser.getId());
        };
    }
}

5. JDBC 레파지토리 실습 (friend)

DB 테이블 생성

CREATE TABLE friend (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    email VARCHAR(255)
);

디렉토리 구조

src/main/java
└── org/example/springjdbc
    └── friendapp
        ├── controller
        │   └── FriendController.java
        │
        ├── domain
        │   └── Friend.java
        │
        ├── repository
        │   └── FriendRepository.java
        │
        ├── service
        │   └── FriendService.java
        │
        └── FriendApplication.java

src/main/resources
└── templates
    └── friends
        ├── addForm.html
        ├── detail.html
        ├── editForm.html
        └── list.html

friendapp 패키지

domain
  • Friend.java
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.Id;

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Friend {
    @Id
    private Long id;
    private String name;
    private String email;
}
repository
  • FriendRepository.java
import org.example.springjdbc.friendapp.domain.Friend;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface FriendRepository extends CrudRepository<Friend, Long> { }
service
  • FriendService.java
import lombok.RequiredArgsConstructor;
import org.example.springjdbc.friendapp.domain.Friend;
import org.example.springjdbc.friendapp.repository.FriendRepository;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class FriendService {
    private final FriendRepository friendRepository;

    /** 친구 추가 */
    public Friend addFriend(Friend friend) {
        return friendRepository.save(friend);
    }

    /** 친구 목록 */
    public Iterable<Friend> getFriends() {
        return friendRepository.findAll();
    }

    /** 친구 id 조회 */
    public Friend getFriendById(Long id) {
        return friendRepository.findById(id).orElseThrow();
    }

    /** 친구 정보 업데이트 */
    public Friend updateFriend(Friend friend) {
        return friendRepository.save(friend);
    }

    /** 친구 삭제 */
    public void deleteFriend(Long id) {
        friendRepository.deleteById(id);
    }
}
controller
  • FriendController.java
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.example.springjdbc.friendapp.domain.Friend;
import org.example.springjdbc.friendapp.service.FriendService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequiredArgsConstructor // final 생성자
@RequestMapping("/friends")
public class FriendController {
    private final FriendService friendService;

    /** 친구 추가 (C) */
    // form page
    @GetMapping("/add")
    public String addForm(Model model) {
        return "friends/addForm";
    }
    // post get
    @PostMapping("/add")
    public String addFriend(@ModelAttribute Friend friend) {
        Friend saveFirend = friendService.addFriend(friend);
        System.out.println("[Controller] add :: " + saveFirend);
        return "redirect:/friends/add";
    }

    /** 친구 정보 (R) */
    // list page
    @GetMapping("/list")
    public String getFriends(Model model) {
        Iterable<Friend> friends = friendService.getFriends();
        model.addAttribute("friends", friends);
        System.out.println("[Controller] Iterable :: " + friends);
        return "friends/list";
    }
    // detail
    @GetMapping("/detail/{id}")
    public String detailFriend(Model model, @PathVariable("id") Long id) {
        Friend detailFriend =  friendService.getFriendById(id);
        model.addAttribute("friend", detailFriend);
        System.out.println("[Controller] detailFriend :: " + detailFriend);
        return "friends/detail";
    }


    /** 친구 수정 (U) */
    @GetMapping("/edit/{id}")
    public String editForm(Model model, @PathVariable("id") Long id) {
        Friend editFriend =  friendService.getFriendById(id);
        model.addAttribute("friend", editFriend);
        return "friends/editForm";
    }
    @PostMapping("/edit")
    public String editFriend(@ModelAttribute Friend friend) {
        friendService.updateFriend(friend);
        return "redirect:/friends/list";
    }

    /** 친구 삭제 (D) */
    @GetMapping("/delete/{id}")
    public String deleteFriend(Model model, @PathVariable("id") Long id) {
        friendService.deleteFriend(id);
        return "redirect:/friends/list";
    }

}
FriendApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class FriendApplication {
    public static void main(String[] args) {
        SpringApplication.run(FriendApplication.class, args);
    }
}

template 폴더

friends
  • addForm.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>친구 추가 입력</title>
    <link rel="stylesheet" th:href="@{/css/app.css}">
</head>
<body>
    <header><h1>친구 추가</h1></header>
    <main>
        <section class="section _form">
            <form method="post" th:action="@{/friends/add}">
                <div class="form_item">
                    <div class="field">
                        <label for="name">이름 : </label>
                        <input type="text" id="name" name="name">
                    </div>
                </div>

                <div class="form_item">
                    <div class="field">
                        <label for="email">이메일 : </label>
                        <input type="text" id="email" name="email">
                    </div>
                </div>

                <div class="btn_group">
                    <button type="submit" class="btn _action">친구등록</button>
                </div>
            </form>
        </section>
    </main>
    <footer></footer>
</body>
</html>
  • detail.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>친구 상세정보</title>
    <link rel="stylesheet" th:href="@{/css/app.css}">
</head>
<body>
    <header><h1>친구 정보</h1></header>
    <main>
        <section class="section _detail">
            <div class="detail_area">
                <div class="inner_head">
                    <i class="icon">
                        <img src="http://via.placeholder.com/128x128" alt="">
                    </i>
                    <h2>[[${friend.name}]]님</h2>
                </div>
                <div class="inner_body">
                    <ul class="info_list">
                        <li>
                            <div class="dt">
                                <span>서버 아이디</span>
                            </div>
                            <div class="dd">
                                <span>[[${friend.id}]]</span>
                            </div>
                        </li>
                        <li>
                            <div class="dt">
                                <span>친구 이름</span>
                            </div>
                            <div class="dd">
                                <span>[[${friend.name}]]</span>
                            </div>
                        </li>
                        <li>
                            <div class="dt">
                                <span>친구 이메일</span>
                            </div>
                            <div class="dd">
                                <span>[[${friend.email}]]</span>
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
            <div class="btn_group">
                <a class="btn _primary" th:href="@{/friend/list}">목록으로</a>
                <a class="btn _action" th:href="@{/friends/edit/{id}(id=${friend.id})}">친구 수정</a>
                <a class="btn _secondary" th:href="@{/friends/delete/{id}(id=${friend.id})}">친구 삭제</a>
            </div>
        </section>
    </main>
    <footer></footer>
</body>
</html>
  • editForm.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>친구 정보 수정</title>
    <link rel="stylesheet" th:href="@{/css/app.css}">
</head>
<body>
    <header><h1>친구 정보 수정</h1></header>
    <main>
        <section class="section _form">
            <form method="post" th:action="@{/friends/edit}">
                <input type="hidden" name="id" th:value="${friend.id}">

                <div class="form_item">
                    <div class="field">
                        <label for="name">이름 : </label>
                        <input type="text" id="name" name="name" th:value="${friend.name}">
                    </div>
                </div>

                <div class="form_item">
                    <div class="field">
                        <label for="email">이메일 : </label>
                        <input type="text" id="email" name="email" th:value="${friend.email}">
                    </div>
                </div>

                <div class="btn_group">
                    <button type="submit" class="btn _action">정보 수정</button>
                </div>
            </form>
        </section>
    </main>
    <footer></footer>
</body>
</html>
  • list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>친구 목록</title>
    <link rel="stylesheet" th:href="@{/css/app.css}">
</head>
<body>
    <header><h1>친구 목록</h1></header>
    <main>
        <section class="section _list">
            <div class="table_area" th:if="${!friends.empty}">
                <table>
                    <colgroup>
                        <col style="width: calc(100%/3)">
                        <col style="width: calc(100%/3)">
                        <col style="width: calc(100%/3)">
                    </colgroup>
                    <thead>
                        <tr>
                            <th>아이디</th>
                            <th>이름</th>
                            <th>이메일</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr th:each="friend : ${friends}">
                            <td><span>[[${friend.id}]]</span></td>
                            <td>
                                <a
                                    class="underline_btn"
                                    th:href="@{/friends/detail/{id}(id=${friend.id})}"
                                    th:title="|${friend.name}님 정보 보기|">
                                    [[${friend.name}]]
                                </a>
                            </td>
                            <td><span>[[${friend.email}]]</span></td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <div class="nodata" th:if="${friends.empty}">
                <p>친구 목록이 없습니다.<br>추가해주세요.</p>
            </div>
            <div class="btn_group">
                <a class="btn _primary" th:href="@{/friends/add}">친구 등록</a>
            </div>
        </section>
    </main>
    <footer></footer>
</body>
</html>
  • resource/static/css/app.css
/* 파일하나로 처리 */
* { margin: 0; padding: 0; box-sizing: border-box; } 
ul li, ol li { list-style: none; } 
a { text-decoration: none; } 

html { font-size: 62.5%; width: 100%; min-height: 100%; } 

body { display: flex; flex-direction: column; font-size: 1.4rem; font-family: "Pretendard", "Noto Sans KR", sans-serif; line-height: 1.5; color: #333; min-height: 100dvh; background: #f4f4f4; } 


/* 헤더 */
header { position: sticky; top: 0; margin: 0; padding: 20px 0; width: 100%; background: #005386; color: #fff; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.05); } 

header h1 { font-size: 1.8rem; color: #fff; text-align: center; } 

/* 메인 섹션 */
main { width: 100%; padding: 20px; flex: 1; } 

section { 
    width: 100%; margin: 20px 0; 
    &._form { margin-inline: auto; max-width: 400px; background: #fff; padding: 30px 25px; border-radius: 12px; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08); } 
}

/* 각 폼 항목 */
.form_item { margin-bottom: 20px; } 

.field { display: flex; flex-direction: column; } 

label { margin-bottom: 6px; font-weight: 600; color: #555; } 

/* 입력창 스타일 */
input[type="text"] { padding: 10px 12px; border: 1px solid #ccc; border-radius: 6px; font-size: 1.4rem; transition: border-color 0.2s, box-shadow 0.2s; } 

input[type="text"]:focus { border-color: #4caf50; outline: none; box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.2); } 

/* 버튼 */
.btn_group { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 20px; } 

.btn { display: inline-flex; width: auto; color: #fff; font-size: 1.4rem; font-weight: 600; padding: 10px 24px; border: none; border-radius: 6px; cursor: pointer; transition: background-color 0.2s, transform 0.1s; } 

.btn { 
    &._primary { background-color: #4650e0; } 
    &._action { background-color: #4caf50; } 
    &._secondary { background-color: #555555; } 
}

.btn:hover { /*background-color:; */}

.btn:active { transform: scale(0.98); } 

/* 테이블 */
.table_area { width: 100%; padding: 20px; } 
.table_area { } 
.table_area table { position:relative; width: 100%; border-collapse: collapse; border-top: 1px solid transparent; } 
.table_area table::before { content:''; position:absolute; top:-1px; width:100%; height:1px; background-color: #121315; } 
.table_area table tr:first-child th,
.table_area table tr:first-child td { border-top: 0; } 
.table_area table tr th:first-child,
.table_area table tr td:first-child { border-left: 0; } 
.table_area table tr th:last-child,
.table_area table tr td:last-child { border-right: 0; } 
.table_area table th { color: #121315; background-color: #F3F6FB; } 
.table_area table td { color: #576072; background-color: #fff; } 
.table_area table td > strong { font-weight: 600; } 
.table_area table td .align_right { display:block; text-align:right; } 
.table_area table th,
.table_area table td { padding: 8px; border: 1px solid #E7EDF6; font-size: 1.4rem; } 
.table_area table tbody th,
.table_area table tbody td { text-align: left; } 
.table_area table thead th,
.table_area table thead + tbody th,
.table_area table thead + tbody td { text-align: center; } 
.table_area table thead tr th[rowspan],
.table_area table thead tr:last-child:not(:first-child) th { border-bottom-color: #E7EDF6; } 
.table_area table + table { margin-top: 24px !important; } 

etc

자주사용되는 CRUD 쿼리 메서드

메서드 이름 패턴 생성되는 SQL 예시 설명
findBy{필드명} WHERE 필드 = ? findByName 정확히 일치하는 값 조회
findBy{필드1}And{필드2} WHERE 필드1 = ? AND 필드2 = ? findByNameAndEmail 여러 조건 AND 연산
findBy{필드1}Or{필드2} WHERE 필드1 = ? OR 필드2 = ? findByNameOrEmail 여러 조건 OR 연산
findBy{필드}Like WHERE 필드 LIKE ? findByNameLike LIKE 검색 (직접 패턴 지정)
findBy{필드}Containing WHERE 필드 LIKE '%?%' findByNameContaining 부분 문자열 포함 검색
findBy{필드}StartingWith WHERE 필드 LIKE '?%' findByNameStartingWith 특정 문자로 시작하는 검색
findBy{필드}EndingWith WHERE 필드 LIKE '%?' findByNameEndingWith 특정 문자로 끝나는 검색
findBy{필드}IgnoreCase WHERE UPPER(필드) = UPPER(?) findByNameIgnoreCase 대소문자 무시 검색
findBy{필드}GreaterThan WHERE 필드 > ? findByAgeGreaterThan 값보다 큰 조건
findBy{필드}LessThan WHERE 필드 < ? findByAgeLessThan 값보다 작은 조건
findBy{필드}Between WHERE 필드 BETWEEN ? AND ? findByAgeBetween 범위 검색
findBy{필드}IsNull WHERE 필드 IS NULL findByEmailIsNull NULL 값 검색
findBy{필드}IsNotNull WHERE 필드 IS NOT NULL findByEmailIsNotNull NOT NULL 값 검색
findBy{필드}In WHERE 필드 IN (?) findByNameIn 여러 값 중 하나와 일치
findBy{필드}NotIn WHERE 필드 NOT IN (?) findByNameNotIn 여러 값과 일치하지 않음
starweb
@starweb :: starweb 님의 블로그

starweb 님의 블로그 입니다.

공감하셨다면 구독도 환영합니다!

목차