В каких форматах SQL-запросы использовались в последнем проекте на Java?

«В каких форматах SQL-запросы использовались в последнем проекте на Java?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В зависимости от слоя и сложности, использовались несколько подходов:

1. Spring Data JPA с @Query Для декларативных, статических запросов прямо в репозитории.

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // JPQL (объектно-ориентированный)
    @Query("SELECT u FROM User u WHERE u.active = true AND u.role = :role")
    List<User> findActiveUsersByRole(@Param("role") String role);

    // Нативный SQL (для специфичных операций СУБД)
    @Query(value = "SELECT * FROM users WHERE last_login < NOW() - INTERVAL '30 days'", nativeQuery = true)
    List<User> findInactiveUsers();
}

2. JOOQ для сложных и типобезопасных запросов Использовался в модулях с интенсивной аналитикой.

// Генерация типобезопасного DSL из схемы БД
List<Order> orders = dslContext
    .select(ORDERS.ORDER_ID, ORDERS.AMOUNT, CUSTOMERS.NAME)
    .from(ORDERS)
    .join(CUSTOMERS).on(ORDERS.CUSTOMER_ID.eq(CUSTOMERS.ID))
    .where(ORDERS.STATUS.eq("COMPLETED").and(ORDERS.CREATED_AT.gt(LocalDate.now().minusDays(7))))
    .fetchInto(Order.class);

3. JDBC PreparedStatement для динамических запросов Применялся, когда условия запроса формировались в runtime.

StringBuilder sql = new StringBuilder("SELECT * FROM products WHERE 1=1 ");
List<Object> params = new ArrayList<>();

if (category != null) {
    sql.append("AND category = ? ");
    params.add(category);
}
if (minPrice != null) {
    sql.append("AND price >= ? ");
    params.add(minPrice);
}

PreparedStatement stmt = connection.prepareStatement(sql.toString());
for (int i = 0; i < params.size(); i++) {
    stmt.setObject(i + 1, params.get(i));
}

4. Criteria API / QueryDSL для динамического построения запросов на уровне JPA, избегая конкатенации строк.