← Назад к вопросам
Какой REST метод используешь для удаления сущности в CRUD-приложении?
1.3 Junior🔥 271 комментариев
#REST API и микросервисы#Основы Java
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
REST методы для удаления сущности
Краткий ответ
Для удаления сущности в CRUD-приложении используется HTTP метод DELETE. Стандартный формат: DELETE /api/v1/resources/{id}
Стандартный DELETE запрос
Вот классический пример CRUD операции удаления:
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteById(id);
return ResponseEntity.noContent().build(); // 204 No Content
}
}
Компоненты DELETE запроса:
- HTTP метод: DELETE
- URL: /api/v1/resources/{id}
- Status код: 204 No Content (успешно удалено)
- Body: обычно пуст (нет данных для отправки)
Статус коды для DELETE
| Код | Значение | Применение |
|---|---|---|
| 204 No Content | Успешно удалено, нет тела ответа | Стандартный случай |
| 200 OK | Успешно, возвращаем информацию | Когда нужно вернуть удалённую сущность |
| 202 Accepted | Запрос принят, удаление асинхронное | Долгие операции |
| 404 Not Found | Ресурс не найден | Пытались удалить несуществующий ID |
| 403 Forbidden | Доступ запрещен | Нет прав на удаление |
Полный пример с обработкой ошибок
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
private final UserService userService;
@DeleteMapping("/{id}")
public ResponseEntity<?> deleteUser(@PathVariable Long id) {
try {
// Проверяем существование
User user = userService.findById(id)
.orElseThrow(() -> new ResourceNotFoundException(
"User not found with id: " + id));
// Проверяем права доступа
if (!userService.canDelete(getCurrentUser(), user)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(new ErrorResponse("No permission to delete"));
}
// Удаляем сущность
userService.deleteById(id);
// Возвращаем 204 No Content
return ResponseEntity.noContent().build();
} catch (ResourceNotFoundException e) {
return ResponseEntity.notFound().build(); // 404
}
}
}
Альтернативные подходы
1. Мягкое удаление (Soft Delete)
Вместо полного удаления из БД помечаем запись как удалённую:
@Entity
@Table(name = "users")
public class User {
@Id
private Long id;
private String name;
@Column(name = "deleted_at")
private LocalDateTime deletedAt; // null = не удалён
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
// Вместо удаления, устанавливаем deletedAt = now()
userService.softDelete(id);
return ResponseEntity.noContent().build();
}
Плюсы:
- Можно восстановить данные
- Сохраняется история
- Внешние ключи не ломаются
Минусы:
- Усложняет запросы (везде WHERE deleted_at IS NULL)
- Занимает больше места в БД
2. Каскадное удаление
Удаление связанных сущностей:
@Entity
public class User {
@OneToMany(mappedBy = "user", cascade = CascadeType.DELETE)
private List<Post> posts; // Удалятся автоматически
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
// При удалении User удалятся и все его Posts
userService.deleteById(id);
return ResponseEntity.noContent().build();
}
Пакетное удаление
Если нужно удалить несколько сущностей:
@PostMapping("/batch-delete")
public ResponseEntity<Void> batchDelete(@RequestBody List<Long> ids) {
userService.deleteByIds(ids);
return ResponseEntity.noContent().build();
}
// Service
public void deleteByIds(List<Long> ids) {
userRepository.deleteAllByIdInBatch(ids);
}
REST vs GraphQL
В GraphQL удаление выглядит по-другому:
mutation {
deleteUser(id: "123") {
success
message
}
}
Но это всё равно использует DELETE операцию на уровне логики.
Лучшие практики для DELETE
-
Используй правильный HTTP статус:
- 204 No Content — стандарт для DELETE
- 200 OK — если возвращаешь данные удалённой сущности
-
Проверяй права доступа:
@DeleteMapping("/{id}") @PreAuthorize("hasRole('ADMIN') or @securityService.isOwner(#id, principal)") public ResponseEntity<Void> deleteUser(@PathVariable Long id) { ... } -
Используй транзакции:
@Transactional public void deleteUser(Long id) { // Откатится всё, если произойдёт ошибка } -
Логируй удаления:
@DeleteMapping("/{id}") public ResponseEntity<Void> deleteUser(@PathVariable Long id) { logger.info("User deleted: {} by {}", id, getCurrentUser()); userService.deleteById(id); return ResponseEntity.noContent().build(); } -
Рассмотри асинхронное удаление для больших объёмов:
@DeleteMapping("/batch") public ResponseEntity<Void> batchDeleteAsync(@RequestBody List<Long> ids) { asyncService.scheduleDelete(ids); // Асинхронно return ResponseEntity.accepted().build(); // 202 Accepted }
Выводы
- DELETE — правильный HTTP метод для удаления
- 204 No Content — стандартный ответ
- Рассмотри мягкое удаление для критичных данных
- Всегда проверяй права доступа перед удалением
- Используй транзакции для целостности данных