Есть ли способ расширить службу Spring, чтобы управлять унаследованным объектом без дублирования кода?

Я играю с приложением Spring с двумя контроллерами и двумя службами, которые управляют связанными объектами, и я хотел бы избежать дублирования кода. У меня, например, есть класс Person с его PersonRepository

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Person {
    @Id
    Long id;
    String name;
    String surname;
}

И его ребенок User со своим UserRepository

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class User extends Person {
    String login;
    String password;
}

У меня есть простой сервис Person с бизнес-логикой:

@Service
public class PersonService {
    @Autowired
    PersonRepository repo;

    public Iterable<Person> getAll() {
        // Busines Logic
        return repo.findAll();
    }

}

Есть ли способ создать UserService, расширяющий или проксирующий PersonService и реализующий какой-то репозиторий, «скрывающий»? Что-то вроде этого:

@Service
public class UserService extends PersonService {    
    @Autowired
    UserRepository repo;
}

это, очевидно, дает эту ошибку: Несоответствие типов: невозможно преобразовать Iterable<Person> в Iterable<User> с помощью такого контроллера.

@RestController
@RequestMapping(value = "/test", produces = MediaType.APPLICATION_JSON_VALUE)
public class DemoController {

    @Autowired
    UserService service;

    @GetMapping
    public void items() {
        Iterable<User> persons = service.getAll();
        return;
    }
}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
232
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Попробуйте следующую структуру:

Общий сервис и репозиторий:

@NoRepositoryBean
public interface PersonRepository<T> extends JpaRepository<T, Long> {

}
public class PersonService<T extends Person> {

    protected PersonRepository<T> repository;

    public <R extends PersonRepository<T>> PersonService(R repository) {
        this.repository = repository;
    }

    public Iterable<T> getAll() {
        return repository.findAll();
    }

}

Для сущности пользователя:

public interface UserRepository extends PersonRepository<User> {

}

@Service
public class UserService extends PersonService<User> {

    public UserService(UserRepository repository) {
        super(repository);
    }

    public void additionalMethod() {
        User user = repository.getOne(1L);
    }
}

И я добавил сущность компании по примеру сущности пользователя:

public interface CompanyRepository extends PersonRepository<Company> {

}
@Service
public class CompanyService extends PersonService<Company> {

    public CompanyService(CompanyRepository repository) {
        super(repository);
    }

    public void additionalMethod() {
        Optional<Company> company = repository.findById(1L);
    }
}

Другие вопросы по теме