Какую базу данных вы использовали в последнем проекте и как с ней работали?

Ответ

В последнем проекте в качестве основной реляционной базы данных использовалась PostgreSQL. Для взаимодействия с ней применялся стек Spring Data JPA поверх Hibernate.

Пример сущности и репозитория:

// Сущность (Entity)
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String email;

    // Другие поля, связи (@OneToMany, @ManyToOne)
    // Getters and Setters
}

// Репозиторий (Spring Data JPA)
public interface UserRepository extends JpaRepository<User, Long> {
    // Декларативный метод для поиска
    Optional<User> findByEmail(String email);

    // Пример запроса с @Query (JPQL)
    @Query("SELECT u FROM User u WHERE u.createdAt > :date")
    List<User> findUsersCreatedAfter(@Param("date") LocalDateTime date);
}

Дополнительные инструменты и практики:

  • Миграции схемы: Использовали Flyway для версионирования и применения изменений структуры БД (DDL).
  • Сложные запросы: Для динамических или сложных запросов применяли QueryDSL или нативные SQL-запросы (@Query(nativeQuery = true)).
  • Кэширование: Для повышения производительности часто запрашиваемых данных подключали Redis в качестве кэша второго уровня (L2 cache) или для хранения сессий.

Ответ 18+ 🔞

А, ну это классика, блядь! В прошлом проекте мы, как нормальные люди, взяли PostgreSQL — она ж как швейцарские часы, надёжная сука. А чтобы с ней не общаться на голом SQL, как дикари, натянули сверху Spring Data JPA с Hibernate. Это ж как переводчик с человеческого на язык таблиц, блядь!

Смотри, как это выглядит, если по-простому:

// Это типа паспорт для записи в таблице "users"
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // Главный номер, сам растёт, красота

    @Column(nullable = false, unique = true)
    private String email; // Почта, и чтоб одна на весь мир, ёпта!

    // Тут ещё куча полей могла быть, связи всякие...
    // Getters and Setters
}

// А это — волшебная говорящая коробка для работы с юзерами
public interface UserRepository extends JpaRepository<User, Long> {
    // Спросишь у неё "найди по мылу" — она сама запрос сообразит, ядрёна вошь!
    Optional<User> findByEmail(String email);

    // А если надо похитрее, так и напишешь запрос прямо тут
    @Query("SELECT u FROM User u WHERE u.createdAt > :date")
    List<User> findUsersCreatedAfter(@Param("date") LocalDateTime date);
}

И всё, казалось бы, ебушки-воробушки! Ан нет, жизнь-то сложнее.

Что ещё прикручивали, чтобы не облажаться:

  • Миграции (Flyway): А то как без них? Представь, у тебя десять программистов начинают в схему БД тыкать пальцами, как слепые котята. Flyway — это такой строгий архитектор, который говорит: «Все изменения — по версиям, по порядку, и ни хуя самовольничать!». Чтоб на проде не вышло, что у тебя таблица есть, а у коллеги — уже нет, пиздец.

  • Сложные запросы: Spring Data JPA — она хороша, пока запросы простые. А как только нужно «найди тех, у кого имя как Иван, но заказов больше пяти, а ещё они из Москвы, но только если не заблокированы» — тут уже Hibernate начинает тупить, как мартышлюшка. Поэтому для такой динамической хуйни брали QueryDSL — он запросы из кусочков лепит. А для совсем уж запредельной логики — нативные SQL-запросы (@Query(nativeQuery = true)). Да, приходилось пачкать руки, зато быстро, блядь.

  • Кэширование (Redis): Ну а куда без этого? База — она хоть и быстрая, но не железная. Когда каждый второй запрос летит за одними и теми же данными (типа «список городов» или «настройки пользователя»), гонять это в PostgreSQL — это просто издевательство. Redis ставили как быстрый буфер. Туда складывали часто нужную хуйню, и приложение сразу оттуда хватало, не дергая основную базу. Иногда его же для хранения сессий юзали — чтобы кластер не тупил, где какой пользователь залогинен.

Вот так и жили: JPA для рутины, а когда припрет — достаём тяжёлую артиллерию в виде нативных запросов и Redis. Главное — понимать, где какой инструмент ебёт эффективнее.