Лабораторная работа 3: Реализация DTO, Mapper и Repository в Spring Boot приложении с PostgreSQL
1. Создание DTO (Data Transfer Object)
- Базовый DTO для сущности User
public class UserDTO { private Long id; private String username; private String email; // Геттеры и сеттеры } - DTO для создания сущности
UserCreateDTO.javapublic class UserCreateDTO { @NotBlank private String username; @Email private String email; } - DTO для обновления сущности
UserUpdateDTO.javapublic class UserUpdateDTO { private String username; private String email; } - DTO с проекциями (для сложных запросов)
public interface UserProjection { String getUsername(); String getEmail(); } - Валидация DTO
public class UserCreateDTO { @Size(min = 3, max = 50) private String username; } - Ломбок-аннотации
@Data @NoArgsConstructor @AllArgsConstructor public class UserDTO { private Long id; private String username; private String email; } - DTO для связанных сущностей
public class UserWithPostsDTO { private UserDTO user; private List<PostDTO> posts; } - Конвертер дат в DTO
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") private LocalDateTime createdAt;
2. Реализация Mapper
- Ручной маппинг
public UserDTO toDto(User user) { UserDTO dto = new UserDTO(); dto.setId(user.getId()); dto.setUsername(user.getUsername()); return dto; } - Использование MapStruct
Добавьте зависимость:<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.5.5.Final</version> </dependency> - Интерфейс маппера
UserMapper.java@Mapper(componentModel = "spring") public interface UserMapper { UserDTO toDto(User user); User fromDto(UserDTO dto); } - Кастомные методы маппера
@AfterMapping default void enrichDto(User user, @MappingTarget UserDTO dto) { dto.setFullName(user.getFirstName() + " " + user.getLastName()); } - Маппинг коллекций
List<UserDTO> toDtoList(List<User> users); - Игнорирование полей
@Mapping(target = "password", ignore = true) UserDTO toDto(User user); - Маппинг разных типов полей
@Mapping(target = "createdDate", expression = "java(user.getCreatedAt().format(DateTimeFormatter.ISO_DATE))") UserDTO toDto(User user);
3. Настройка Repository
- Базовый репозиторий
public interface UserRepository extends JpaRepository<User, Long> {} - Кастомные запросы с @Query
@Query("SELECT u FROM User u WHERE u.email LIKE %:domain") List<User> findByEmailDomain(@Param("domain") String domain); - Нативные SQL-запросы
@Query(value = "SELECT * FROM users WHERE active = true", nativeQuery = true) List<User> findActiveUsers(); - Projections в репозиториях
List<UserProjection> findByUsernameContaining(String keyword); - Pagination и сортировка
Page<User> findByStatus(String status, Pageable pageable); - Методы с Optional
Optional<User> findByEmail(String email); - Кастомный репозиторий
public interface CustomUserRepository { List<User> findInactiveUsers(); } - Реализация кастомного репозитория
public class CustomUserRepositoryImpl implements CustomUserRepository { @PersistenceContext private EntityManager em; // Реализация методов } - Наследование кастомного репозитория
public interface UserRepository extends JpaRepository<User, Long>, CustomUserRepository {} - Auditing репозиториев
@EntityListeners(AuditingEntityListener.class) public class User { @CreatedDate private LocalDateTime createdAt; }
Пример интеграции в сервисном слое
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final UserMapper userMapper;
public UserDTO createUser(UserCreateDTO dto) {
User user = userMapper.fromCreateDto(dto);
User saved = userRepository.save(user);
return userMapper.toDto(saved);
}
public Page<UserDTO> getAllUsers(Pageable pageable) {
return userRepository.findAll(pageable)
.map(userMapper::toDto);
}
}
Рекомендации по форматированию (для Word)
- Используйте стили Heading 2 для разделов DTO, Mapper, Repository
- Код оформляйте моноширинным шрифтом (например, Consolas 10pt)
- Настройте автоматическое оглавление
- Для каждого раздела используйте нумерованные списки
Вывод
В ходе работы были реализованы все ключевые компоненты работы с данными: DTO для безопасной передачи данных, мапперы для преобразования между слоями и репозитории с различными вариантами доступа к данным. Полученная архитектура соответствует best practices современной Spring-разработки.