Форум программистов, компьютерный форум, киберфорум
Java EE (J2EE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 20.09.2013
Сообщений: 50

Дженерикс

18.03.2020, 19:26. Показов 669. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
На данный момент реализовано так, есть сущность ProjectEntity (справочник проектов) и его методы реализованы в DirectoryController, всё прекрасно работало пока мне не пришлось добавлять в функционал еще один справочник задач (TaskEntity). Я конечно могу так же добавлять методы для нового справочника и всё будет работать, но у двух справочник одни и те же CRUD операции, и получится дублирование кода, что не есть хорошо. Подскажите как реализовать методы 2х сущностей в одном контроллере, имею представление о том что нужно все абстрагировать, но реализация не понятна. Всем заранее спасибо, и здоровья
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package com.dilau.tsservice.controller;
 
import com.dilau.tsservice.dto.ProjectDto;
import com.dilau.tsservice.entity.ProjectEntity;
import com.dilau.tsservice.exception.ResourceNotFoundException;
import com.dilau.tsservice.repos.ProjectRepo;
import com.dilau.tsservice.repos.TaskRepo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
 
import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;
 
 
@RestController
@Slf4j
@RequestMapping("/project")
@RequiredArgsConstructor
public class DirectoryController {
 
    private final ModelMapper modelMapper;
    private final ProjectRepo projectRepo;
    private final TaskRepo taskRepo;
 
    @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
    public List<ProjectDto> getAllProject() {
        List<ProjectEntity> lists = (List<ProjectEntity>) projectRepo.findAll();
        return lists.stream().map(this::toDto).collect(Collectors.toList());
    }
 
    @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    public ProjectDto getProjectById(@PathVariable(value = "id") Long id) {
        return toDto(projectRepo.findById(id)
                  .orElseThrow(() -> new ResourceNotFoundException("Project", "id", id)));
    }
 
    @PostMapping(value = "/addProject", consumes = MediaType.APPLICATION_JSON_VALUE, produces =
            MediaType.APPLICATION_JSON_VALUE)
    public void createProject(@RequestBody ProjectDto projectDto) {
        ProjectEntity projectEntity = toEntity(projectDto);
        ProjectEntity projectEntity1 = projectRepo.save(projectEntity);
    }
 
    @PostMapping(value = "/updateProject/{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces =
            MediaType.APPLICATION_JSON_VALUE)
    public void updateProject(@PathVariable(value = "id") Long id, @Valid @RequestBody ProjectDto projectDetail) {
        ProjectDto projectDto = toDto(projectRepo.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Project", "id", id)));
        projectDto.setId(projectDetail.getId());
        projectDto.setCode(projectDetail.getCode());
        projectDto.setValueKz(projectDetail.getValueKz());
        projectDto.setValueRu(projectDetail.getValueRu());
        ProjectEntity projectEntity = toEntity(projectDto);
        projectRepo.save(projectEntity);
 
    }
 
    @DeleteMapping(value = "/deleteProject/{id}", produces =
            MediaType.APPLICATION_JSON_VALUE)
    public void deleteProject(@PathVariable(value = "id") Long id) {
        ProjectDto projectDto = toDto(projectRepo.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Project", "id", id)));
        ProjectEntity projectEntity = toEntity(projectDto);
        projectRepo.delete(projectEntity);
    }
 
    private ProjectEntity toEntity(ProjectDto projectDto) {
        return modelMapper.map(projectDto, ProjectEntity.class);
    }
 
    private ProjectDto toDto(ProjectEntity projectEntity) {
        return modelMapper.map(projectEntity, ProjectDto.class);
    }
 
 
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.dilau.tsservice.dto;
 
 
import lombok.Data;
 
@Data
public class ProjectDto {
 
    private Long id;
    private String code;
    private String valueKz;
    private String valueRu;
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.dilau.tsservice.dto;
 
import lombok.Data;
 
@Data
public class TaskDto {
 
    private Long id;
    private String code;
    private String valueKz;
    private String valueRu;
 
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.dilau.tsservice.entity;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.util.List;
 
 
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "project")
public class ProjectEntity {
 
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;
 
    @NotBlank
    @Column(name = "code", nullable = false)
    private String code;
 
    @NotBlank
    @Column(name = "value_kz", nullable = false)
    private String valueKz;
 
    @NotBlank
    @Column(name = "value_ru", nullable = false)
    private String valueRu;
 
    @OneToMany(mappedBy = "projectEntity")
    //@JsonBackReference
    private List<DashBoardEntity> dashBoardEntityList;
 
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.dilau.tsservice.entity;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.util.List;
 
 
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "task")
public class TaskEntity {
 
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;
 
    @NotBlank
    @Column(name = "code", nullable = false)
    private String code;
 
    @NotBlank
    @Column(name = "value_kz", nullable = false)
    private String valueKz;
 
    @NotBlank
    @Column(name = "value_ru", nullable = false)
    private String valueRu;
 
    @OneToMany(mappedBy = "taskEntity")
    //@JsonBackReference
    private List<DashBoardEntity> dashBoardEntityList;
}
0
25 / 21 / 6
Регистрация: 10.12.2018
Сообщений: 115
19.03.2020, 07:11
я бы сказал что не по феншую использовать один и тот же репозиторий для разных типов данных. т.е. репозитории должны быть разными чтоб каши не было. другое дело что ты можешь обращаться не к репозиторию на прямую из контроллера а добавить прослойку сервисов. но опять же чтобы дергать разные справочники лучше использовать разные api. подведу итог: да, рефакторинг это хорошо, но надо не забывать что у нас при этом не должно получаться каши. т.е. для разных справочников луче использовать отдельные api и отдельные репозитории

Добавлено через 2 минуты
лучше напиши лишний класс но чтобы код было легче читать и проще масштабировать чем ты свалишь всё в одну кучу и через месяц уже сам не сможешь понять для каких целей ты так написал

Добавлено через 5 минут
а про реализацию: использовать не репозиторий а сервис типо диспатчера... можно сделать класс сингл тон, туда добавить свои круд репозитории, и хешкарту которая содержит HashMap<string, Function<CrudRepository, E>> проинициализировать мапу и дергать по ключу нужные метод с нужным репозиторием...
1
Эксперт Java
 Аватар для KEKCoGEN
2399 / 2224 / 565
Регистрация: 28.12.2010
Сообщений: 8,672
19.03.2020, 10:47
Кенес, у тебя две одинаковые таблицы. Зачем? Сделай одну таблицу и заведи там поле type (PROJECT/TASK) и проблем не будет
1
0 / 0 / 0
Регистрация: 20.09.2013
Сообщений: 50
19.03.2020, 12:07  [ТС]
Я думал над этим, но это хорошо если у меня будет 2 справочника, а если функционал таймшита увеличится и будет уже 5-10 справочников тогда уже поддерживать будет тяжелее. Конечно тема Дженериков не легкая, но уж лучше сразу через это пройти. Вопрос не в том что бы сделать что бы было, а в том что бы сделать правильно и красиво. Спасибо за ответ.

Добавлено через 4 минуты
Цитата Сообщение от JavaDoc Посмотреть сообщение
лучше напиши лишний класс но чтобы код было легче читать и проще масштабировать чем ты свалишь всё в одну кучу и через месяц уже сам не сможешь понять для каких целей ты так написал
Лишний класс написать не проблема, но что если справочников будет на много больше, допустим 10 и для каждого писать всё с нуля от репо до контроллера, по этому и хотелось бы все абстрагировать логику описать один раз, и что бы при добавлении нового справочника просто инжектить. Возможно я не понятно всё описал, и не верно сформулировал, сорри, а за ответ и обратную связь огромное спасибо
0
Эксперт Java
 Аватар для KEKCoGEN
2399 / 2224 / 565
Регистрация: 28.12.2010
Сообщений: 8,672
19.03.2020, 12:41
Цитата Сообщение от Кенес Посмотреть сообщение
а если функционал таймшита увеличится и будет уже 5-10 справочников тогда уже поддерживать будет тяжелее.
да хоть 100500. Поддержка такого кода будет легче

Цитата Сообщение от Кенес Посмотреть сообщение
Вопрос не в том что бы сделать что бы было, а в том что бы сделать правильно и красиво.
это и есть правильно с точки зрения архитектуры
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Ответ Создать тему
Новые блоги и статьи
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
Отправка уведомления на почту при создании или изменении элементов справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной записи электронной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru