Что такое Spring Data JDBC?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Spring Data JDBC
Spring Data JDBC — это модуль Spring Data, предоставляющий лёгкий и минималистичный доступ к реляционным базам данных через JDBC. Это альтернатива JPA/Hibernate, когда нужна простота и полный контроль над SQL запросами.
Основная идея
Spring Data JDBC следует принципу DDD (Domain-Driven Design) и предоставляет:
- Repository паттерн для абстракции доступа к БД
- Минимум магии — нет прокси-объектов и ленивой загрузки
- Прямое управление SQL — вы пишете запросы
- Слабая связанность — простые POJO без JPA аннотаций
Зависимости
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Основные компоненты
1. Сущность (Entity)
Простой POJO класс с аннотациями Spring Data JDBC:
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
import org.springframework.data.relational.core.mapping.Column;
@Table("users")
public class User {
@Id
private Long id; // Автоматически генерируется БД
@Column("name")
private String name;
@Column("email")
private String email;
@Column("created_at")
private LocalDateTime createdAt;
// Конструкторы, getter, setter
public User() {}
public User(String name, String email) {
this.name = name;
this.email = email;
this.createdAt = LocalDateTime.now();
}
// Getters and Setters
public Long getId() { return id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// ...
}
2. Repository интерфейс
Расширяет CrudRepository или PagingAndSortingRepository:
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
// Метод-запрос (spring-data-jdbc конвертирует в SQL)
Optional<User> findByEmail(String email);
// Кастомный SQL запрос
@Query("SELECT * FROM users WHERE name LIKE :name")
List<User> searchByName(String name);
// Удаление по условию
void deleteByEmail(String email);
// Подсчёт записей
long countByNameContaining(String namePattern);
}
Использование Repository
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// Создание нового пользователя
public User createUser(String name, String email) {
User user = new User(name, email);
return userRepository.save(user); // INSERT
}
// Получение по ID
public User getUserById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("User not found"));
}
// Поиск по email
public User findByEmail(String email) {
return userRepository.findByEmail(email)
.orElseThrow(() -> new IllegalArgumentException("User not found"));
}
// Поиск по имени
public List<User> searchUsers(String name) {
return userRepository.searchByName("%" + name + "%");
}
// Обновление
public User updateUser(Long id, String newName) {
User user = getUserById(id);
user.setName(newName);
return userRepository.save(user); // UPDATE
}
// Удаление
public void deleteUser(Long id) {
userRepository.deleteById(id); // DELETE
}
// Получение всех пользователей с пагинацией
public Page<User> getAllUsers(int page, int size) {
return userRepository.findAll(PageRequest.of(page, size));
}
}
Методы Query по умолчанию
Spring Data JDBC генерирует SQL на основе имена метода:
// SELECT * FROM users WHERE email = ?
Optional<User> findByEmail(String email);
// SELECT * FROM users WHERE name = ? AND email = ?
Optional<User> findByNameAndEmail(String name, String email);
// SELECT * FROM users WHERE age > ?
List<User> findByAgeGreaterThan(int age);
// SELECT * FROM users WHERE name LIKE ?
List<User> findByNameContaining(String name);
// SELECT COUNT(*) FROM users WHERE active = true
long countByActive(boolean active);
// SELECT * FROM users WHERE active = true ORDER BY created_at DESC
List<User> findByActiveOrderByCreatedAtDesc(boolean active);
Кастомные SQL запросы
@Repository
public interface ProductRepository extends CrudRepository<Product, Long> {
// Явный SELECT запрос
@Query("SELECT * FROM products WHERE category = :category AND price > :minPrice")
List<Product> findExpensiveByCategory(
@Param("category") String category,
@Param("minPrice") BigDecimal minPrice
);
// INSERT/UPDATE/DELETE с @Modifying
@Modifying
@Query("UPDATE products SET quantity = quantity - 1 WHERE id = :id")
void decreaseQuantity(@Param("id") Long id);
// Удаление
@Modifying
@Query("DELETE FROM products WHERE price < :minPrice")
int deleteByMinPrice(@Param("minPrice") BigDecimal minPrice);
}
Связи между сущностями
Spring Data JDBC не поддерживает ленивую загрузку и требует явного управления связями:
@Table("orders")
public class Order {
@Id
private Long id;
private String orderNumber;
// Агрегированная ссылка на User (не связь)
private Long userId; // Вручную управляем ID
// Для загрузки полного User нужен свой запрос
public void loadUserData(UserRepository userRepository) {
// Явная загрузка
}
}
Транзакции
@Service
public class TransactionService {
@Autowired
private UserRepository userRepository;
@Autowired
private OrderRepository orderRepository;
@Transactional // Все операции в одной транзакции
public void processOrder(Long userId, Order order) {
// Проверяем пользователя
User user = userRepository.findById(userId)
.orElseThrow(() -> new UserNotFoundException("User not found"));
// Сохраняем заказ
order.setUserId(user.getId());
orderRepository.save(order);
// Если возникнет исключение — откатит обе операции
}
}
Spring Data JDBC vs JPA
| Характеристика | Spring Data JDBC | JPA/Hibernate |
|---|---|---|
| Сложность | Простая | Сложная |
| Производительность | Лучше (нет магии) | Может быть медленнее |
| Управление запросами | Явное | Неявное (генерируется) |
| Ленивая загрузка | Нет | Да (проблемы N+1) |
| Кривая обучения | Низкая | Высокая |
| Гибкость | Ограниченная | Полная |
| Связи | Ручное управление | Автоматическое |
Когда использовать
Используй Spring Data JDBC когда:
- Нужна максимальная простота и понятность
- Работаешь с относительно простой схемой БД
- Критична производительность
- Предпочитаешь явное управление SQL
- Проект маленький или средний
Используй JPA когда:
- Сложная архитектура с множеством связей
- Нужна кроссплатформенность (разные БД)
- Важна гибкость и функционал ORM
- Большой enterprise проект
Spring Data JDBC — отличный выбор для разработчиков, которые хотят контролировать SQL без сложности полнофункционального ORM.