Spring에서는 데이터베이스와의 효율적인 통신을 위해 Spring JDBC와 Spring Data JPA를 제공합니다. 각각의 사용법과 관련 개념을 단계적으로 설명드리겠습니다.
Spring JDBC는 JDBC(Java Database Connectivity)를 더 편리하게 사용할 수 있도록 도와줍니다. JdbcTemplate은 Spring JDBC에서 제공하는 주요 클래스입니다.
spring-boot-starter-jdbc를 의존성으로 추가하면 자동 설정됩니다.Maven 의존성:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>@Component
public class UserRepository {
    private final JdbcTemplate jdbcTemplate;
    public UserRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    public List<User> findAll() {
        String sql = "SELECT * FROM users";
        return jdbcTemplate.query(sql, (rs, rowNum) -> 
            new User(rs.getLong("id"), rs.getString("name"), rs.getString("email"))
        );
    }
}public void save(User user) {
    String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
    jdbcTemplate.update(sql, user.getName(), user.getEmail());
}Spring Data JPA는 JPA(Java Persistence API)를 더 편리하게 사용할 수 있도록 도와주는 라이브러리입니다.
ORM(Object-Relational Mapping)을 기반으로 데이터베이스와 객체 간의 매핑을 처리합니다.
<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>spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password: 
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
    // Getters, Setters, and Constructors
}Spring Data JPA에서는 Repository 인터페이스를 통해 CRUD 작업을 쉽게 수행할 수 있습니다.
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}사용 예시:
@Service
public class UserService {
    private final UserRepository userRepository;
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    public User saveUser(User user) {
        return userRepository.save(user);
    }
    public List<User> findAllUsers() {
        return userRepository.findAll();
    }
}Spring Data JPA는 메서드 이름으로 쿼리를 생성할 수 있는 기능을 제공합니다.
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name); // SELECT * FROM user WHERE name = ?
    List<User> findByEmailContaining(String keyword); // LIKE '%keyword%'
}JPQL은 엔티티 객체를 기반으로 쿼리를 작성하는 언어입니다.
@Query("SELECT u FROM User u WHERE u.email LIKE %:keyword%")
List<User> searchByEmail(@Param("keyword") String keyword);Spring Data JPA는 페이징과 정렬을 간단하게 지원합니다.
public List<User> findAllUsers(Pageable pageable) {
    return userRepository.findAll(pageable).getContent();
}Pageable pageable = PageRequest.of(0, 10, Sort.by("name").ascending());
List<User> users = userRepository.findAll(pageable).getContent();Spring은 데이터베이스 작업에서 트랜잭션을 효과적으로 관리할 수 있는 기능을 제공합니다.
주로 @Transactional 어노테이션을 통해 트랜잭션을 처리합니다.
@Service
public class UserService {
    private final UserRepository userRepository;
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    @Transactional
    public void saveUserAndEmail(User user) {
        userRepository.save(user);
        // 일부 작업 중 예외 발생 시 전체 롤백
        if (user.getEmail() == null) {
            throw new IllegalArgumentException("Email cannot be null");
        }
    }
}트랜잭션이 실행되는 방식(전파 수준)을 설정할 수 있습니다.
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser(User user) {
    userRepository.save(user);
}추가 학습 자료
-[스프링 DB 1편 - 데이터 접근 핵심 원리] JDBC의 이해
-[Spring][DB] 스프링 DB 1편 - 데이터 접근 핵심 원리