← Назад к вопросам

Что такое сессия в Hibernate?

1.7 Middle🔥 191 комментариев
#ORM и Hibernate

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Session в Hibernate: Полное объяснение

Определение

Session в Hibernate — это основной интерфейс для взаимодействия с базой данных. Это единица работы, которая управляет жизненным циклом сущностей (entities), их загрузкой, сохранением и удалением. Session — это оболочка над JDBC соединением.

Основные функции Session

1. Создание и управление сущностями

SessionFactory sessionFactory = new Configuration()
    .configure()
    .buildSessionFactory();

// Создание сессии
Session session = sessionFactory.openSession();

// Работа с сущностями
Person person = new Person("John", 25);
session.save(person);  // Сохранение в БД

session.close();  // Закрытие сессии

2. Загрузка данных

Session session = sessionFactory.openSession();

// Получить объект по ID
Person person = session.get(Person.class, 1L);

// HQL запрос
Query query = session.createQuery("from Person where age > :age");
query.setParameter("age", 18);
List<Person> adults = query.list();

session.close();

3. Обновление

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Person person = session.get(Person.class, 1L);
person.setAge(26);
session.update(person);  // Помечает для обновления

tx.commit();
session.close();

Жизненный цикл сущности

Четыре состояния:

// 1. TRANSIENT (Новая сущность)
Person person = new Person("Alice", 25);
// Объект существует только в памяти, Hibernate его не знает

// 2. PERSISTENT (Управляемая сущность)
Session session = sessionFactory.openSession();
session.save(person);  // Теперь сущность в контексте
// Hibernate отслеживает изменения

// 3. DETACHED (Отсоединённая сущность)
session.close();
// Сущность больше не управляется Session
// Но данные в ней ещё есть

// 4. REMOVED (Удалённая сущность)
Session session2 = sessionFactory.openSession();
session2.delete(person);
// Сущность будет удалена из БД

Контекст и Identity Map

Session содержит Identity Map — кеш, который гарантирует, что в памяти существует только одна копия объекта:

Session session = sessionFactory.openSession();

Person p1 = session.get(Person.class, 1L);  // SELECT из БД
Person p2 = session.get(Person.class, 1L);  // Из кеша, БЕЗ SELECT!

System.out.println(p1 == p2);  // true! Один и тот же объект
session.close();

Типы операций CRUD

Save

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Person person = new Person("John", 25);
session.save(person);  // INSERT

tx.commit();
session.close();

Get / Load

Session session = sessionFactory.openSession();

// get — SELECT сразу
Person p1 = session.get(Person.class, 1L);  // Ленивая загрузка

// load — возвращает proxy, SELECT при обращении к данным
Person p2 = session.load(Person.class, 2L);  // Прокси объект
System.out.println(p2.getAge());  // Теперь SELECT!

session.close();

Update

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Person person = new Person();
person.setId(1L);
person.setName("Updated Name");

session.update(person);  // UPDATE в БД

tx.commit();
session.close();

SaveOrUpdate

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Person person = /* существующий объект */;
// Если ID есть — UPDATE, если нет — INSERT
session.saveOrUpdate(person);

tx.commit();
session.close();

Delete

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Person person = session.get(Person.class, 1L);
session.delete(person);  // DELETE из БД

tx.commit();
session.close();

Типы загрузки

Eager Loading (Жадная загрузка)

@Entity
public class Person {
    @ManyToOne(fetch = FetchType.EAGER)
    private Company company;  // Загрузится с Person
}

Session session = sessionFactory.openSession();
Person person = session.get(Person.class, 1L);
// SELECT person и company в одном запросе (JOIN)

Lazy Loading (Ленивая загрузка)

@Entity
public class Person {
    @ManyToOne(fetch = FetchType.LAZY)  // По умолчанию
    private Company company;  // Загрузится отдельно
}

Session session = sessionFactory.openSession();
Person person = session.get(Person.class, 1L);  // SELECT только person
System.out.println(person.getCompany().getName());  // SELECT company

Best Practices

1. Используйте try-with-resources

try (Session session = sessionFactory.openSession()) {
    Transaction tx = session.beginTransaction();
    
    Person person = new Person("John", 25);
    session.save(person);
    
    tx.commit();
} catch (Exception e) {
    e.printStackTrace();
}
// Сессия закроется автоматически

2. N+1 Query Problem

// ❌ Плохо
List<Person> people = session.createQuery("from Person").list();
for (Person p : people) {
    System.out.println(p.getCompany().getName());  // N запросов!
}

// ✅ Хорошо
List<Person> people = session.createQuery(
    "from Person p join fetch p.company"
).list();
for (Person p : people) {
    System.out.println(p.getCompany().getName());  // Уже в памяти
}

3. Используйте flush и clear

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

for (int i = 0; i < 10000; i++) {
    Person person = new Person("Person " + i, i);
    session.save(person);
    
    if (i % 100 == 0) {
        session.flush();   // Отправить в БД
        session.clear();   // Очистить кеш
    }
}

tx.commit();
session.close();

4. Не забывайте коммит транзакции

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Person person = new Person("John", 25);
session.save(person);

// ❌ Без коммита изменения НЕ попадут в БД
// tx.commit();

session.close();

Различие между Persistence Context и Cache

ПараметрPersistence ContextCache
УровеньСессияSessionFactory
Время жизниПока Session открытаПока живо приложение
ВидимостьТолько этой SessionДля всех Sessions
РазмерОграниченМожет быть огромным

Практический пример: REST Controller

@RestController
@RequestMapping("/api/people")
public class PersonController {
    @Autowired
    private SessionFactory sessionFactory;
    
    @PostMapping
    public ResponseEntity<Person> createPerson(@RequestBody Person person) {
        try (Session session = sessionFactory.openSession()) {
            Transaction tx = session.beginTransaction();
            session.save(person);
            tx.commit();
            return ResponseEntity.ok(person);
        }
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<Person> getPerson(@PathVariable Long id) {
        try (Session session = sessionFactory.openSession()) {
            Person person = session.get(Person.class, id);
            return person != null ? ResponseEntity.ok(person) 
                                  : ResponseEntity.notFound().build();
        }
    }
}

Заключение

Session в Hibernate — это основной инструмент для работы с БД в приложениях на Java. Понимание жизненного цикла сущностей, типов загрузки и best practices критично для писания эффективного и надёжного кода.

Что такое сессия в Hibernate? | PrepBro