0

Создание репозитория Spring без сущности

5

Я хочу использовать интерфейс репозитория Spring Data для выполнения нативных запросов — я считаю, что это самый простой способ из-за низкой сложности.

Однако при расширении интерфейса, например, CrudRepository<T, ID>, мне нужно указать T — мою сущность, которая недоступна.

Мои нативные запросы не возвращают конкретную сущность, поэтому каков лучший способ создать репозиторий Spring без сущности?

5 ответ(ов)

0

CrudRepository и JpaRepository не предназначены для работы без пары <Entity, ID>.

Вам лучше создать пользовательский репозиторий, внедрить EntityManager и выполнять запросы оттуда:

@Repository
public class CustomNativeRepositoryImpl implements CustomNativeRepository {

    @Autowired
    private EntityManager entityManager;

    @Override
    public Object runNativeQuery() {
        return entityManager.createNativeQuery("myNativeQuery")
            .getSingleResult();
    }
}

Таким образом, вы получите более гибкое управление запросами и сможете использовать произвольные SQL-запросы.

0

В данный момент в JPA нет функциональности для создания репозиториев, которые бы использовали только нативные запросы или JPQL/HQL запросы с использованием аннотации @Query. Чтобы обойти это ограничение, вы можете создать заглушечный объект, который будет вставлен в расширяемый интерфейс, как показано ниже:

@Entity
public class RootEntity {
    @Id
    private Integer id;
}

@Repository
public interface MyRepository extends JpaRepository<RootEntity, Integer> {
}

Таким образом, вы можете использовать этот подход для реализации своих собственных методов с нативными или JPQL/HQL запросами, добавляя их в ваш репозиторий.

0

Это работает для нас. Обратите внимание на менеджер сущностей в примере:

Ссылка на статью

@Repository
public class MyRepository {

    @PersistenceContext
    EntityManager entityManager;

    public void doSomeQuery() {
        Query query = entityManager.createNativeQuery("SELECT foo FROM bar");
        List<?> results = query.getResultList();
        // Дальнейшая обработка результатов...
    }

}

В этом примере мы используем EntityManager для выполнения нативного SQL-запроса. Метод createNativeQuery позволяет создавать запрос, который будет выполняться непосредственно в базе данных. После выполнения запроса мы получаем список результатов с помощью метода getResultList().

0

Вы можете просто аннотировать вашу реализацию с помощью @Repository и получить экземпляр EntityManager.

public interface ProductFilterRepository {
    Page<Product> filter(FilterTO filter, Pageable pageable);
}

@Repository
@AllArgsConstructor
public class ProductFilterRepositoryImpl implements ProductFilterRepository {

    private final EntityManager em;

    @Override
    public Page<Product> filter(FilterTO filter, Pageable pageable) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Product> cq = cb.createQuery(Product.class);
        Root<Product> root = cq.from(Product.class);
        List<Predicate> predicates = new ArrayList<>();

        if (filter.getPriceMin() != null) {
            predicates.add(cb.ge(root.get("price"), filter.getPriceMin()));
        }
        if (filter.getPriceMax() != null) {
            predicates.add(cb.le(root.get("price"), filter.getPriceMax()));
        }
        if (filter.getBrands() != null && !filter.getBrands().isEmpty()) {
            predicates.add(root.get("brand").in(filter.getBrands()));
        }
        if (filter.getCategories() != null && !filter.getCategories().isEmpty()) {
            predicates.add(root.get("category").in(filter.getCategories()));
        }
        cq.where(predicates.toArray(new Predicate[0]));
        TypedQuery<Product> tq = em.createQuery(cq);
        tq.setMaxResults(pageable.getPageSize());
        tq.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());

        CriteriaQuery<Long> countCq = cb.createQuery(Long.class);
        countCq.select(cb.count(countCq.from(Product.class)));
        countCq.where(predicates.toArray(new Predicate[0]));
        TypedQuery<Long> countTq = em.createQuery(countCq);
        Long count = countTq.getSingleResult();

        return new PageImpl<>(tq.getResultList(), pageable, count);
    }
}

В данном примере мы создаем интерфейс ProductFilterRepository с методом filter, который принимает объект фильтра и параметры постраничной навигации. Реализация ProductFilterRepositoryImpl, аннотированная @Repository, предоставляет конкретную реализацию этого метода с использованием EntityManager для создания произвольных критериев выборки.

Обратите внимание на использование CriteriaBuilder и CriteriaQuery для создания условий фильтрации, что позволяет нам гибко управлять запросами к базе данных. Мы также используем Pageable для управления постраничным выводом результатов.

0

Использование JdbcTemplate может рассматриваться как альтернатива, когда у вас нет конкретного класса сущности для получаемого результата нативного запроса. Для выполнения запросов данных с помощью JdbcTemplate требуется класс POJO для результата и маппер, реализующий интерфейс RowMapper для данного класса POJO.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь