Скажем, у меня есть абстрактная сущность
@MappedSuperclass
@Data
public abstract class AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(nullable = false, updatable = false)
protected Integer id;
@Column(nullable = false, unique = true)
protected String name;
}
с неким абстрактным репозиторием
@NoRepositoryBean
public interface AbstractRepository<C extends AbstractEntity> extends JpaRepository<C, Integer> {}
, который должен служить одной зависимостью для нескольких сущностей. Сущности расширяют абстрактную сущность и, таким образом, AbstractRepository:
public interface RealEntityRepository extends AbstractRepository<RealEntity> {}
В моем сервисе я хочу использовать наследование jpa, чтобы избавиться от конструктора-разветвителя (он раздут из-за слишком большого количества realEntityRepos) и реализации методов для каждой сущности , Поэтому вместо x методов, подобных этому, для каждой сущности
void findRealEntity(RealEntity entity) {
entity.setId(realEntityRepository.findOne(entity.getName())
.map(RealEntity ::getId)
.orElseThrow(() -> new SomeException(entity.getName())));
}
Я хочу иметь только один вызов метода, как в следующем псевдокоде (я знаю, что нельзя создавать экземпляры абстрактных классов), который принимает сущность в качестве абстрактной сущности для аргумент, вызывает дочернее репо и выполняет методы jpa в этом конкретном c дочернем репо.
void findEntity(AbstractEntity entity) {
entity.setId(abstractEntityRepository.findOne(entity.getName())
.map(AbstractEntity::getId)
.orElseThrow(() -> new SomeException(entity.getName())));
}
Это мой сервис на данный момент, он работает так, но он раздувается:
@Service
public class SomeService {
private final RealEntity1Repository realEntity1Repository;
private final RealEntity2Repository realEntity2Repository;
private final RealEntity3Repository realEntity3Repository ;
... 5 more times ..
public SomeService(RealEntity1Repository realEntity1Repository, RealEntity2Repository realEntity2Repository,
RealEntity3Repository realEntity3Repository,
... 5 more) {
this.realEntity1Repository = realEntity1Repository;
this.realEntity2Repository = realEntity2Repository;
this.realEntity3Repository = realEntity3Repository;
... 5 more
}
... some methods
void findRealEntity1(RealEntity1 entity) {
entity.setId(realEntity1Repository.findOne(entity.getName())
.map(RealEntity1::getId)
.orElseThrow(() -> new SomeException(entity.getName())));
}
void findRealEntity2(RealEntity2 entity) {
entity.setId(realEntity2Repository.findOne(entity.getName())
.map(RealEntity2::getId)
.orElseThrow(() -> new SomeException(entity.getName())));
}
...
ОБНОВЛЕНИЕ
Спасибо подсказкам @Antoniosss. Я решил проблему!
Добавьте Optional<C> findByName(String name);
в SuperRepository, а затем создайте новый сервис, который реализует репозиторий сущностей, определяющий c методы транзакций. Вызовите этот сервис в предыдущем сервисе при реализации отображения между AbstractEntity и методами, определяющими сущность c:
public void mapAbstractEntity(AbstractEntity abstractEntity) {
if (abstractEntity instanceof RealEntity1 { // call RealEntity1 method from service}
else if (abstractEntity instanceof RealEntity2) { ... }