Piszę rest api do obsługi helpdesk w springu.
https://github.com/konradszafranski/helpdesk-backend
Chciałbym teraz dodać encję "sprawa serwisowa" nie za bardzo wiem jak to zrobić żeby było to napisane w miarę sensownie i czysto.
Encja sprawa serwisowa powinna być w relacji z osobą która utworzyła sprawę i tą która aktualnie ją obsługuje, myślę o tym żeby zamiast wrzucać wszystkich użytkowników do jednej tabeli utworzyć dla każdego typu pracownika klasę. Dzięki temu rekordy z tabeli users nie będą wchodziły ze sobą pośrednio w relacje i będzie można stworzyć unikalny zbiór uprawnień dla każdego z typów.
@MappedSuperclass
public abstract class User implements UserDetails {
// implementacja UserDetails
}
@Entity
@Table(name = "customerService")
public class CustomerService extends User {
//List<CustomerServicePermission> up;
//List<Utworzone sprawy> us;
}
@Entity
@Table(name = "serviceTech")
public class ServiceTech extends User {
//List<ServiceTechPermission> up;
//List<Utworzone sprawy> us;
//List<Obsługiwane sprawy> os;
}
@Entity
@Table(name = "admin")
public class Admin extends User {
//List<AdminPermission> up;
//List<Obsługiwane sprawy> os;
}
Zastanawiam się czy w takiej sytuacji dla każdego typu użytkownika powinno się utworzyć odpowiednio Service?
Bo jeśli nie to klasa UserService kożystałaby conajmniej z 3 repozytoriów - CustomerServiceRepo, ServiceTechRepo, AdminRepo i musiałaby każdorazowo określać jakiego typu jest użytkownik na którym należy wykonać działanie.
@Service
public class UserService implements UserDetailsService {
EmployeeRepo employeeRepository;
UserPermissionRepo userPermissionRepository;
EmployeeWrapper employeeWrapper;
PasswordEncoder passwordEncoder;
public UserService(EmployeeRepo employeeRepo, UserPermissionRepo userPermissionRepo, EmployeeWrapper employeeWrapper, PasswordEncoder passwordEncoder) {
this.employeeRepository = employeeRepo;
this.userPermissionRepository = userPermissionRepo;
this.employeeWrapper = employeeWrapper;
this.passwordEncoder = passwordEncoder;
}
public void createNewUser(CreateUserRequest createUserRequest) {
Employee employee = employeeWrapper.employeeRequestToEmployee(createUserRequest);
employee.setPassword(passwordEncoder.encode(employee.getPassword()));
try {
employeeRepository.saveAndFlush(employee);
} catch (Exception e) {
System.out.println("exception " + e.getMessage() + " " + e.getCause());
}
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
return employeeRepository.findUserByName(username);
} catch (Exception e) {
System.out.println(e.toString());
throw e;
}
}
public List<Employee> getListOfUsers() throws HibernateException {
List<Employee> employeeList = employeeRepository.findAll();
return employeeList;
}
@PostConstruct
public void createSampleUser() {
try {
UserPermission userRole = new UserPermission("GET_ALL_CASES");
userPermissionRepository.save(userRole);
UserPermission userPermission2 = new UserPermission("ADD_EMPLOYEE");
userPermissionRepository.save(userPermission2);
Set<String> userPermissions = new HashSet<>();
userPermissions.add("ADD_EMPLOYEE");
CreateUserRequest createUserRequest = new CreateUserRequest("k_sz",
"cat",
userPermissions,
"name",
"surname",
"POPO",
"544190270");
createNewUser(createUserRequest);
} catch (Exception e) {
System.out.println("employeeService");
System.out.println(e);
}
}
}
Czy w takiej sytuacji np. metoda createNewUser musiałaby być albo przeciążona dla każdego typu użytkownika albo trzeba byłoby sprawdzać typ za pomocą switch albo instanceof żeby wiadomo było do której z tabel zapisać danego użytkownika?
Nie wiem czy to jest poprawne podejście ponieważ jeśli każda metoda będzie albo w 3 egzemplarzach albo będzie ustalała typ to klasa może się mocno rozrosnąć wraz ze zwiększaniem liczby metod.
Natomiast metoda @Override loadUserByUsername(String username), sprawdzałaby każdorazowo wszystkie tabele w poszukiwaniu odpowiedniego użytkownika ponieważ jedyny jej argument to "String username"
W jaki sposób można byłoby to sensownie zaprojektować?