← Назад к вопросам
Как ведет себя get() в Hibernate, если объект отсутствует
2.0 Middle🔥 171 комментариев
#ORM и Hibernate#Базы данных и SQL
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Поведение get() в Hibernate при отсутствии объекта
EntityManager.getReference() vs session.get()
В Hibernate существует важное различие между двумя методами для получения объекта по ID:
1. session.get() — Возвращает null
// Hibernate Session API (старый стиль)
Session session = sessionFactory.openSession();
User user = session.get(User.class, 99L); // Если не найдено
// user == null
Метод get() возвращает null если объект с заданным ID не существует в базе данных. Это безопасный способ проверить наличие объекта.
Session session = sessionFactory.openSession();
User user = session.get(User.class, userId);
if (user != null) {
System.out.println("Пользователь найден: " + user.getName());
} else {
System.out.println("Пользователь не найден");
}
2. EntityManager.getReference() — Выбрасывает исключение
// JPA API (современный стиль)
EntityManager em = entityManagerFactory.createEntityManager();
try {
User user = em.getReference(User.class, 99L);
// Если не найдено — EntityNotFoundException!
} catch (EntityNotFoundException e) {
System.out.println("Объект не найден");
}
Метод getReference() выбрасывает EntityNotFoundException, если объект не существует. Важно: исключение выбрасывается не сразу, а при обращении к полям объекта!
3. JpaRepository.getById() — Отложенная ошибка
// Spring Data JPA
@Repository
public interface UserRepository extends JpaRepository<User, Long> {}
// Использование
User user = userRepository.getById(99L); // Не выбрасывает исключение сразу!
System.out.println(user.getName()); // EntityNotFoundException выбросится здесь!
getById() возвращает прокси-объект Hibernate, но исключение выбрасывается только при первом обращении к его полям (lazy loading).
4. JpaRepository.findById() — Безопасный вариант
// Рекомендуемый подход
Optional<User> user = userRepository.findById(99L);
if (user.isPresent()) {
System.out.println("Найден: " + user.get().getName());
} else {
System.out.println("Не найден");
}
// Или более компактно
user.ifPresentOrElse(
u -> System.out.println("Найден: " + u.getName()),
() -> System.out.println("Не найден")
);
// Или с get()
User user = userRepository.findById(99L)
.orElseThrow(() -> new NotFoundException("User not found"));
findById() возвращает Optional — это самый безопасный и явный способ.
Сравнительная таблица
Метод | Не найдено | Когда выбросит
------------------------|-------------------|------------------
session.get() | null | Никогда
EntityManager.get() | null | Никогда
EntityManager.getRef() | Прокси | При обращении
session.load() | Прокси | При обращении
getById() (Spring) | Прокси | При обращении
findById() (Spring) | Optional.empty() | Никогда
Практический пример: обработка ошибок
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository repository;
// Вариант 1: Возвращаем DTO или null
public UserDto getUserOrNull(Long id) {
return repository.findById(id)
.map(this::toDto)
.orElse(null);
}
// Вариант 2: Выбрасываем исключение (предпочтительно)
public UserDto getUserOrThrow(Long id) {
return repository.findById(id)
.map(this::toDto)
.orElseThrow(() -> new UserNotFoundException(
"User with id " + id + " not found"
));
}
// Вариант 3: Устанавливаем default значение
public UserDto getUserOrDefault(Long id) {
return repository.findById(id)
.map(this::toDto)
.orElseGet(() -> UserDto.anonymous());
}
private UserDto toDto(User user) {
return new UserDto(user.getId(), user.getName());
}
}
Ошибки, которых нужно избегать
// ❌ ОПАСНО: LazyInitializationException
User user = userRepository.getById(id);
// сессия закрывается
Session session = em.unwrap(Session.class);
session.close();
// Теперь попытка доступа выбросит исключение!
System.out.println(user.getName());
// ✅ ПРАВИЛЬНО: Используй findById с Optional
Optional<User> user = userRepository.findById(id);
if (user.isPresent()) {
System.out.println(user.get().getName());
}
Рекомендации
- Используй
findById()с Optional — это явно и безопасно - Избегай
getById()— отложенное выбрасывание исключения опасно - Используй
get()только когда нужен null — редкий случай - Всегда обрабатывай отсутствие объекта явно через Optional или try-catch
- Выбрасывай кастомные исключения если объект должен существовать