От JDBC до Spring Data: освоение баз данных в Java-разработке

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Начинающие и опытные Java-разработчики, желающие улучшить свои навыки работы с базами данных.
  • Студенты и специалисты, проходящие обучение по программированию, заинтересованные в практике работы с базами данных.
  • Программисты, желающие узнать о современных инструментах и методах доступа к базам данных в Java.

    Работа с базами данных — это ключевая компетенция каждого Java-разработчика. Без неё вы не сможете создать полноценное корпоративное приложение, управлять данными пользователей или разработать масштабируемый сервис. Независимо от того, делаете вы первые шаги в программировании или уже знакомы с основами Java, понимание инструментов взаимодействия с БД откроет для вас новые возможности. В этой статье мы пройдем путь от базового JDBC до продвинутого Spring Data, рассмотрим реальный код и разберём типичные проблемы, с которыми сталкиваются разработчики. 🚀

Хотите не просто читать о работе с базами данных, а научиться применять эти знания на практике? Курс Java-разработки от Skypro предлагает глубокое погружение в работу с БД — от базовых принципов JDBC до продвинутых возможностей Spring Data JPA. Вместо абстрактной теории вас ждут реальные проекты с наставником, который поможет избежать типичных ошибок и выработать правильные привычки программирования.

Основы работы с базами данных на Java: от А до Я

Прежде чем погружаться в код, важно понять, как Java взаимодействует с базами данных на концептуальном уровне. Вся работа с БД в Java строится вокруг нескольких ключевых технологий и паттернов.

Существует три основных уровня абстракции при работе с базами данных в Java:

  • JDBC (Java Database Connectivity) — низкоуровневый API, обеспечивающий прямое взаимодействие с базами данных через SQL-запросы
  • ORM (Object-Relational Mapping) — промежуточный слой, отображающий объекты Java на записи в реляционной базе данных. Наиболее популярная реализация — Hibernate
  • Spring Data — высокоуровневая абстракция над ORM, предоставляющая готовые репозитории и методы для типовых операций

Эволюция этих технологий отражает переход от прямой работы с SQL к объектно-ориентированному подходу, где база данных становится "прозрачной" для разработчика. 🧩

Технология Уровень абстракции Производительность Простота использования
JDBC Низкий Высокая Низкая
Hibernate Средний Средняя Средняя
Spring Data Высокий Средняя Высокая

Прежде чем начать работу с любой из этих технологий, вам потребуются:

  1. Java Development Kit (JDK), версии 8 и выше
  2. Драйвер JDBC для выбранной базы данных (например, MySQL, PostgreSQL)
  3. Сама база данных (локальная или удаленная)
  4. Интегрированная среда разработки (IDE) — IntelliJ IDEA, Eclipse, NetBeans

Зависимости для проекта удобнее всего подключать через системы сборки Maven или Gradle. Например, для MySQL в pom.xml добавьте:

xml
Скопировать код
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>

Михаил Сергеев, Senior Java Developer На заре моей карьеры я столкнулся с типичной проблемой новичков — утечками соединений с базой данных. Наше веб-приложение периодически "падало" под нагрузкой, и долгое время мы не могли понять причину. Логи показывали ошибку "Too many connections".

Оказалось, я забывал закрывать соединения в блоке finally. После каждого запроса ресурсы не освобождались, и со временем пул соединений исчерпывался. Решение было простым: использовать конструкцию try-with-resources:

Java
Скопировать код
try (Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query)) {
// работа с данными
} catch (SQLException e) {
e.printStackTrace();
}

Этот паттерн автоматически закрывает ресурсы даже при возникновении исключений. С тех пор я следую правилу: никогда не управляй ресурсами вручную, если язык предоставляет автоматические механизмы.

Пошаговый план для смены профессии

JDBC подключение и выполнение SQL запросов в Java

JDBC — это фундамент для всех Java-технологий работы с базами данных. Даже если вы в итоге будете использовать Hibernate или Spring Data, понимание JDBC необходимо для эффективной отладки и оптимизации. 🔍

Процесс подключения к базе данных через JDBC включает следующие шаги:

  1. Загрузка JDBC драйвера
  2. Установление соединения с базой данных
  3. Создание объекта Statement
  4. Выполнение SQL-запроса
  5. Обработка результатов
  6. Закрытие соединения

Рассмотрим пример подключения к MySQL базе данных:

Java
Скопировать код
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DatabaseConnector {
private static final String URL = "jdbc:mysql://localhost:3306/mydb";
private static final String USER = "username";
private static final String PASSWORD = "password";

public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USER, PASSWORD);
}

public static void main(String[] args) {
try (Connection connection = getConnection()) {
System.out.println("Соединение с БД успешно установлено!");
} catch (SQLException e) {
System.err.println("Ошибка подключения к БД: " + e.getMessage());
}
}
}

URL соединения содержит важную информацию:

  • jdbc: — протокол
  • mysql: — тип базы данных
  • //localhost:3306/ — расположение сервера и порт
  • mydb — название базы данных

После установления соединения можно выполнить SQL-запрос и получить данные:

Java
Скопировать код
import java.sql.*;

public class JdbcQuery {
public static void main(String[] args) {
String query = "SELECT id, name, email FROM users";

try (Connection conn = DatabaseConnector.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query)) {

while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");

System.out.println("ID: " + id + ", Имя: " + name + ", Email: " + email);
}

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

Для выполнения параметризованных запросов используйте PreparedStatement — он защищает от SQL-инъекций и обеспечивает лучшую производительность при повторном выполнении:

Java
Скопировать код
String sql = "SELECT * FROM users WHERE age > ? AND country = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, 18);
pstmt.setString(2, "Россия");
ResultSet rs = pstmt.executeQuery();
// обработка результатов
}

При работе с JDBC учитывайте следующие рекомендации:

  • Всегда закрывайте ресурсы через try-with-resources
  • Используйте PreparedStatement вместо обычного Statement для запросов с параметрами
  • Настройте пул соединений (например, HikariCP, C3P0) для производственной среды
  • Не подставляйте пользовательский ввод напрямую в SQL-запросы
  • Обрабатывайте исключения детально, логируя техническую информацию

CRUD операции с базой данных через JDBC: код и практика

CRUD (Create, Read, Update, Delete) — это четыре основные операции при работе с любой базой данных. Реализация этих операций через JDBC требует написания соответствующих SQL-запросов и их выполнения. 📝

Рассмотрим полноценный пример CRUD-операций на примере таблицы employees:

Операция SQL-запрос JDBC метод
Create INSERT INTO employees VALUES (...) executeUpdate()
Read SELECT * FROM employees executeQuery()
Update UPDATE employees SET ... WHERE id=? executeUpdate()
Delete DELETE FROM employees WHERE id=? executeUpdate()

Александр Петров, Java Team Lead В одном из проектов наша команда столкнулась с серьёзными проблемами производительности. База данных содержала миллионы записей, и стандартные CRUD-операции через JDBC становились узким местом всего приложения.

Для решения проблемы мы внедрили пакетную обработку данных при массовых операциях:

Java
Скопировать код
String sql = "INSERT INTO log_entries (timestamp, level, message) VALUES (?, ?, ?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {

conn.setAutoCommit(false);
for (int i = 0; i < logEntries.size(); i++) {
LogEntry entry = logEntries.get(i);
pstmt.setTimestamp(1, entry.getTimestamp());
pstmt.setString(2, entry.getLevel());
pstmt.setString(3, entry.getMessage());
pstmt.addBatch();

// Выполняем батч каждые 1000 записей
if (i % 1000 == 0) {
pstmt.executeBatch();
}
}
pstmt.executeBatch(); // Выполняем оставшиеся
conn.commit();
} catch (SQLException e) {
conn.rollback();
throw e;
}

Такой подход сократил время обработки с часов до минут. Главный урок: при работе с большими объемами данных всегда используйте пакетную обработку и продумывайте стратегию транзакций.

Теперь создадим класс для работы с объектами Employee:

Java
Скопировать код
public class Employee {
private int id;
private String name;
private String position;
private double salary;

// конструкторы, геттеры, сеттеры
}

И реализуем DAO (Data Access Object) для CRUD-операций:

Java
Скопировать код
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class EmployeeDAO {
private Connection connection;

public EmployeeDAO(Connection connection) {
this.connection = connection;
}

// CREATE
public int createEmployee(Employee employee) throws SQLException {
String sql = "INSERT INTO employees (name, position, salary) VALUES (?, ?, ?)";
try (PreparedStatement pstmt = connection.prepareStatement(sql, 
Statement.RETURN_GENERATED_KEYS)) {
pstmt.setString(1, employee.getName());
pstmt.setString(2, employee.getPosition());
pstmt.setDouble(3, employee.getSalary());

int affectedRows = pstmt.executeUpdate();

if (affectedRows == 0) {
throw new SQLException("Создание сотрудника не удалось");
}

try (ResultSet generatedKeys = pstmt.getGeneratedKeys()) {
if (generatedKeys.next()) {
return generatedKeys.getInt(1);
} else {
throw new SQLException("Не удалось получить ID");
}
}
}
}

// READ
public Employee getEmployeeById(int id) throws SQLException {
String sql = "SELECT * FROM employees WHERE id = ?";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setInt(1, id);

try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
Employee employee = new Employee();
employee.setId(rs.getInt("id"));
employee.setName(rs.getString("name"));
employee.setPosition(rs.getString("position"));
employee.setSalary(rs.getDouble("salary"));
return employee;
}
return null;
}
}
}

// READ ALL
public List<Employee> getAllEmployees() throws SQLException {
List<Employee> employees = new ArrayList<>();
String sql = "SELECT * FROM employees";

try (Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {

while (rs.next()) {
Employee employee = new Employee();
employee.setId(rs.getInt("id"));
employee.setName(rs.getString("name"));
employee.setPosition(rs.getString("position"));
employee.setSalary(rs.getDouble("salary"));
employees.add(employee);
}
}

return employees;
}

// UPDATE
public boolean updateEmployee(Employee employee) throws SQLException {
String sql = "UPDATE employees SET name = ?, position = ?, salary = ? WHERE id = ?";

try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setString(1, employee.getName());
pstmt.setString(2, employee.getPosition());
pstmt.setDouble(3, employee.getSalary());
pstmt.setInt(4, employee.getId());

int affectedRows = pstmt.executeUpdate();
return affectedRows > 0;
}
}

// DELETE
public boolean deleteEmployee(int id) throws SQLException {
String sql = "DELETE FROM employees WHERE id = ?";

try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setInt(1, id);

int affectedRows = pstmt.executeUpdate();
return affectedRows > 0;
}
}
}

Применение данного DAO для выполнения CRUD-операций:

Java
Скопировать код
public class EmployeeManager {
public static void main(String[] args) {
try (Connection conn = DatabaseConnector.getConnection()) {
EmployeeDAO dao = new EmployeeDAO(conn);

// CREATE
Employee newEmployee = new Employee();
newEmployee.setName("Иван Петров");
newEmployee.setPosition("Java Developer");
newEmployee.setSalary(120000.0);
int newId = dao.createEmployee(newEmployee);
System.out.println("Создан новый сотрудник с ID: " + newId);

// READ
Employee found = dao.getEmployeeById(newId);
System.out.println("Найден: " + found.getName());

// UPDATE
found.setSalary(125000.0);
boolean updated = dao.updateEmployee(found);
System.out.println("Обновление успешно: " + updated);

// DELETE
boolean deleted = dao.deleteEmployee(newId);
System.out.println("Удаление успешно: " + deleted);

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

При работе с CRUD-операциями в JDBC помните о следующих важных моментах:

  • Транзакции — используйте conn.setAutoCommit(false) и явные commit()/rollback() для атомарных операций
  • Пакетная обработка — применяйте addBatch() и executeBatch() для массовых операций
  • Работа с ошибками — разные базы данных могут генерировать разные коды ошибок
  • Конкуренция — продумайте стратегию блокировок при параллельном доступе

Работа с Hibernate: упрощаем взаимодействие с БД в Java

Hibernate — это ORM-фреймворк, который автоматизирует процесс отображения классов Java на таблицы базы данных. Он избавляет от необходимости писать сложные SQL-запросы и вручную преобразовывать результаты в объекты. 🧠

Чтобы начать работу с Hibernate, добавьте зависимость в файл pom.xml:

xml
Скопировать код
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.5.Final</version>
</dependency>

Для работы Hibernate необходимо:

  1. Создать классы-сущности с аннотациями JPA
  2. Настроить соединение с базой данных
  3. Создать фабрику сессий (SessionFactory)
  4. Выполнять операции с данными через объект Session

Рассмотрим пример реализации класса Employee для Hibernate:

Java
Скопировать код
import javax.persistence.*;

@Entity
@Table(name = "employees")
public class Employee {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

@Column(name = "name", nullable = false)
private String name;

@Column(name = "position")
private String position;

@Column(name = "salary")
private double salary;

// Конструкторы, геттеры, сеттеры
}

Настройка соединения с базой данных выполняется в файле hibernate.cfg.xml:

xml
Скопировать код
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydb</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.connection.password">password</property>

<property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>

<mapping class="com.example.model.Employee" />
</session-factory>
</hibernate-configuration>

Создание фабрики сессий и утилитного класса для работы с Hibernate:

Java
Скопировать код
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();

private static SessionFactory buildSessionFactory() {
try {
return new Configuration().configure().buildSessionFactory();
} catch (Exception ex) {
System.err.println("Создание SessionFactory не удалось: " + ex);
throw new ExceptionInInitializerError(ex);
}
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}

public static void shutdown() {
getSessionFactory().close();
}
}

Теперь реализуем CRUD-операции с использованием Hibernate:

Java
Скопировать код
import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.List;

public class EmployeeDAO {

// CREATE
public Integer saveEmployee(Employee employee) {
Transaction transaction = null;
Integer employeeId = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {
transaction = session.beginTransaction();
employeeId = (Integer) session.save(employee);
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
e.printStackTrace();
}
return employeeId;
}

// READ
public Employee getEmployeeById(int id) {
try (Session session = HibernateUtil.getSessionFactory().openSession()) {
return session.get(Employee.class, id);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

// READ ALL
@SuppressWarnings("unchecked")
public List<Employee> getAllEmployees() {
try (Session session = HibernateUtil.getSessionFactory().openSession()) {
return session.createQuery("FROM Employee").list();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

// UPDATE
public void updateEmployee(Employee employee) {
Transaction transaction = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {
transaction = session.beginTransaction();
session.update(employee);
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
e.printStackTrace();
}
}

// DELETE
public void deleteEmployee(int id) {
Transaction transaction = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {
transaction = session.beginTransaction();
Employee employee = session.get(Employee.class, id);
if (employee != null) {
session.delete(employee);
}
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
e.printStackTrace();
}
}
}

Применение DAO в рабочем коде:

Java
Скопировать код
public class Main {
public static void main(String[] args) {
EmployeeDAO dao = new EmployeeDAO();

// CREATE
Employee employee = new Employee();
employee.setName("Мария Иванова");
employee.setPosition("QA Engineer");
employee.setSalary(95000.0);

Integer id = dao.saveEmployee(employee);
System.out.println("Сотрудник сохранен с ID: " + id);

// READ
Employee savedEmployee = dao.getEmployeeById(id);
System.out.println("Получен сотрудник: " + savedEmployee.getName());

// UPDATE
savedEmployee.setSalary(100000.0);
dao.updateEmployee(savedEmployee);
System.out.println("Данные сотрудника обновлены");

// READ ALL
List<Employee> employees = dao.getAllEmployees();
System.out.println("Всего сотрудников: " + employees.size());

// DELETE
dao.deleteEmployee(id);
System.out.println("Сотрудник удален");

// Завершаем работу
HibernateUtil.shutdown();
}
}

Преимущества Hibernate по сравнению с чистым JDBC:

  • Минимизация количества написанного вручную кода
  • Автоматическое преобразование между объектами и записями в БД
  • Управление связями между объектами (@OneToMany, @ManyToMany и т.д.)
  • Кеширование на нескольких уровнях для повышения производительности
  • Портируемость между разными базами данных
  • Поддержка ленивой загрузки для оптимизации запросов

Spring Data: интеграция и управление базами данных

Spring Data — это часть экосистемы Spring Framework, которая существенно упрощает работу с базами данных. Она предоставляет абстракцию над Hibernate и другими ORM-фреймворками, позволяя писать минимум кода для типовых операций. 🌱

Для использования Spring Data JPA добавьте зависимость в pom.xml:

xml
Скопировать код
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.6.3</version>
</dependency>

Основные преимущества Spring Data:

  • Репозитории с готовыми методами CRUD
  • Создание запросов на основе имени метода
  • Пагинация и сортировка из коробки
  • Поддержка нативных SQL-запросов и JPQL
  • Аудит данных (кто и когда создал/изменил)
  • Интеграция с другими компонентами Spring

Рассмотрим класс сущности, почти идентичный тому, что использовался для Hibernate:

Java
Скопировать код
import javax.persistence.*;
import lombok.Data;

@Data
@Entity
@Table(name = "employees")
public class Employee {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

@Column(name = "name", nullable = false)
private String name;

@Column(name = "position")
private String position;

@Column(name = "salary")
private double salary;
}

Репозиторий Spring Data — это интерфейс, который наследуется от JpaRepository:

Java
Скопировать код
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface EmployeeRepository extends JpaRepository<Employee, Integer> {

// Поиск по имени
List<Employee> findByName(String name);

// Поиск по должности
List<Employee> findByPosition(String position);

// Поиск сотрудников с зарплатой выше указанной
List<Employee> findBySalaryGreaterThan(double salary);

// Комбинированный поиск
List<Employee> findByNameAndPosition(String name, String position);

// Использование JPQL запроса
@Query("SELECT e FROM Employee e WHERE e.salary BETWEEN :minSalary AND :maxSalary")
List<Employee> findEmployeesWithSalaryBetween(@Param("minSalary") double min, 
@Param("maxSalary") double max);

// Использование нативного SQL запроса
@Query(value = "SELECT * FROM employees WHERE YEAR(hire_date) = :year", nativeQuery = true)
List<Employee> findEmployeesHiredInYear(@Param("year") int year);
}

Настройка соединения с базой данных выполняется в файле application.properties или application.yml:

properties
Скопировать код
# Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# JPA Configuration
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.format_sql=true

Использование репозитория в сервисном слое:

Java
Скопировать код
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
public class EmployeeService {

private final EmployeeRepository employeeRepository;

@Autowired
public EmployeeService(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}

// CREATE
@Transactional
public Employee saveEmployee(Employee employee) {
return employeeRepository.save(employee);
}

// READ
public Optional<Employee> getEmployeeById(int id) {
return employeeRepository.findById(id);
}

// READ ALL
public List<Employee> getAllEmployees() {
return employeeRepository.findAll();
}

// UPDATE
@Transactional
public Employee updateEmployee(Employee employee) {
return employeeRepository.save(employee);
}

// DELETE
@Transactional
public void deleteEmployee(int id) {
employeeRepository.deleteById(id);
}

// Пользовательские методы
public List<Employee> findEmployeesByName(String name) {
return employeeRepository.findByName(name);
}

public List<Employee> findEmployeesBySalaryRange(double min, double max) {
return employeeRepository.findEmployeesWithSalaryBetween(min, max);
}
}

Использование сервиса в контроллере Spring MVC:

Java
Скопировать код
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/employees")
public class EmployeeController {

private final EmployeeService employeeService;

@Autowired
public EmployeeController(EmployeeService employeeService) {
this.employeeService = employeeService;
}

@PostMapping
public ResponseEntity<Employee> createEmployee(@RequestBody Employee employee) {
Employee savedEmployee = employeeService.saveEmployee(employee);
return ResponseEntity.ok(savedEmployee);
}

@GetMapping("/{id}")
public ResponseEntity<Employee> getEmployeeById(@PathVariable int id) {
return employeeService.getEmployeeById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}

@GetMapping
public ResponseEntity<List<Employee>> getAllEmployees() {
List<Employee> employees = employeeService.getAllEmployees();
return ResponseEntity.ok(employees);
}

@PutMapping("/{id}")
public ResponseEntity<Employee> updateEmployee(@PathVariable int id, 
@RequestBody Employee employee) {
employee.setId(id);
Employee updatedEmployee = employeeService.updateEmployee(employee);
return ResponseEntity.ok(updatedEmployee);
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteEmployee(@PathVariable int id) {
employeeService.deleteEmployee(id);
return ResponseEntity.noContent().build();
}

@GetMapping("/search/name/{name}")
public ResponseEntity<List<Employee>> findByName(@PathVariable String name) {
List<Employee> employees = employeeService.findEmployeesByName(name);
return ResponseEntity.ok(employees);
}

@GetMapping("/search/salary")
public ResponseEntity<List<Employee>> findBySalaryRange(
@RequestParam double min, @RequestParam double max) {
List<Employee> employees = employeeService.findEmployeesBySalaryRange(min, max);
return ResponseEntity.ok(employees);
}
}

Spring Data JPA значительно упрощает архитектуру приложения и сокращает количество кода, который необходимо написать для стандартных операций с базой данных. При этом он сохраняет гибкость для настройки сложных запросов и поддерживает различные стратегии загрузки данных.

Вы прошли путь от низкоуровневого JDBC до высокоуровневого Spring Data, познакомившись с основными технологиями доступа к базам данных в Java-экосистеме. Независимо от того, какой подход вы выберете, понимание основ JDBC остается важным фундаментом для диагностики проблем и оптимизации производительности. Для небольших проектов чистый JDBC или Hibernate могут быть достаточными решениями, в то время как для крупных корпоративных приложений Spring Data предоставляет наилучший баланс между простотой разработки и функциональной мощью. Главное — выбрать инструмент, соответствующий сложности задачи, и следовать лучшим практикам управления соединениями, транзакциями и обработки ошибок.

Загрузка...