У меня есть несколько сущностей, и я использую репозитории Spring Data JPA с спецификации запросить мою базу данных. Поэтому я создал общий класс SpecBuilder
для построения моих запросов на основе описания запроса (MyQueryDescriptor
).
public class Specs {
public static <T extends MyEntityIFace> Specification<T> myfind(final MyQueryDescriptor qDesc) {
return new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root,
CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
try {
return SpecBuilder.mySpec(root, criteriaQuery, criteriaBuilder, qDesc);
} catch (Exception e) {
...handle error...
}
}
};
}
}
Мои репозитории:
public interface Entity1DAO extends Repository<Entity1,Long>,
JpaSpecificationExecutor {
}
А также
public interface Entity2DAO extends Repository<Entity2,Long>,
JpaSpecificationExecutor {
}
Я не совсем уверен в трех вещах:
1)
Является ли использование универсального SpecBuilder чистым дизайном?
2)
Есть ли способ избежать написания этих интерфейсов репозитория для каждой сущности? Скажем, общий репозиторий?
3)
Класс MyQueryDescriptor
имеет метод для возврата экземпляра Entity, который будет запрошен.
Каким будет чистый способ получить соответствующий репозиторий на основе класса сущности, избегая случая переключения? Я думал о том, чтобы добавить аннотацию с конкретным классом репозитория к каждой сущности, но это немного неприятно.
Должен ли я создать фабрику и внедрить карту вроде
Entity1.class => Entity1DAO
Entity2.class => Entity2DAO
?
2 ответа
Вы можете использовать наследование сущностей и использовать Spring Expression Language (SpEL), чтобы делать вызовы репозитория для нужных сущностей. Как и в моем последнем обновлении, здесь
JpaSpecificationExecutor
?
Является ли использование универсального SpecBuilder чистым дизайном?
Зависит от того, какие критерии у вас есть для чистого дизайна. Будет ли один и тот же MyQueryDescriptor
работать для разных сущностей? Конечно, у них разные свойства, поэтому вам нужно спросить себя, может ли данный MyQueryDescriptor
быть ошибочно использован для несовместимого объекта и способы, которыми вы могли бы предотвратить это. Мы не можем это комментировать, поскольку не знаем, как работает ваш SpecBuilder
.
Есть ли способ избежать написания этих интерфейсов репозитория для каждой сущности? Скажем, общий репозиторий?
Неа. Впрочем, это не так уж и много шаблонов.
- У класса MyQueryDescriptor есть метод для возврата экземпляра Сущность, которая будет опрошена. Каким чистым способом получить соответствующий репозиторий на основе класса сущности, избегая переключения случай?
Я полагаю, вы могли бы использовать getBeanProvider
во время выполнения, где вы должны определить resolvableType
как CrudRepository<MyEntityType, IdType>
.
Однако на вашем месте я бы подумал о переходе на использование API критериев JPA без абстракции JpaSpecificationExecutor
поверх него. Это, наверное, было бы более естественным. Дизайн репозиториев Spring основан на идее организации репозитория запросов вокруг данной конкретной сущности, тогда как ваш вариант использования, похоже, идет в прямо противоположном направлении - динамически выбирать сущность, а затем находить репозиторий, который подходит, просто для того, чтобы удовлетворить ограничения Spring. Похоже, вы боретесь с фреймворком в этом отношении.
Похожие вопросы
Связанные вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.
findAll()
,save(T)
и т. д., но почему бы не оставить детали на усмотрение? Вы можете позволить системе генерировать приятные вещи, напримерfindThisByThatAndTheOther(T that, T2 theOther);
?findThisByThatAndTheOther(T that, T2 theOther)
, но мой классSpecBuilder
должен иметь возможность создавать все запросы критериев, которые мне нужны. Поэтому создание пустых репозиториев для многих сущностей вызывает много накладных расходов.