Создать репозиторий spring без сущности

#java #spring #spring-boot #jpa #spring-data-jpa

#java #spring #spring-загрузка #jpa #spring-data-jpa

Вопрос:

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

Но при расширении интерфейса, например. CrudRepository<T, ID> Мне нужно написать T — my entity, которая недоступна.

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

Ответ №1:

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

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

   @Repository
  public class CustomNativeRepositoryImpl implements CustomNativeRepository {

    @Autowired
    private EntityManager entityManager;

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

Комментарии:

1. Это не полный код. Что такое CustomNativeRepository и как вы это определяете?

2. В данном случае просто интерфейс, который имеет метод runNativeQuery() общедоступного объекта

3. Было бы лучше добавить этот простой фрагмент для полноты

4. Или, что еще лучше, не иметь интерфейса.

5. Хотя этот ответ кажется правильным, я не понимаю, почему Spring не разрешает интерфейс с @ Repository на нем и @ Query на методах.

Ответ №2:

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

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

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

Комментарии:

1. Это какой-то странный код. Он даже не будет компилироваться. Частный модификатор в интерфейсе? Хорошо, возможно, это опечатка. Но даже изменение интерфейса на class не позволит вашему приложению spring работать.

2. Да, это была опечатка, теперь это должно сработать. Если у вас возникла проблема, можете ли вы предоставить сообщение об ошибке или задать другой вопрос?

Ответ №3:

У нас это работает. Смотрите диспетчер сущностей

https://www.baeldung.com/hibernate-entitymanager

 @Repository
public class MyRepository {

    @PersistenceContext
    EntityManager entityManager;

    public void doSomeQuery(){
        Query query = entityManager.createNativeQuery("SELECT foo FROM bar");
        query.getResultsList()
        ...
    }

}
  

Комментарии:

1. В моем случае это работало с аннотацией @Repository, поэтому я думаю, что это необходимо.

2. @Repository не требуется. @Component будет достаточно @Akankshit_98

Ответ №4:

Вы можете просто прокомментировать свою реализацию с помощью @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 amp;amp; !filter.getBrands().isEmpty()) {
            predicates.add(root.get("brand").in(filter.getBrands()));
        }
        if (filter.getCategories() != null amp;amp; !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);
    }
}
  

Ответ №5:

Если вы используете JPA, вам нужны сущности. Как и в предыдущих ответах, вы можете создавать NativeQueries или использовать Criterions API непосредственно из EntityManager.

Некоторая документация о пользовательских отчетах и обычном поведении репозитория:

https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html#repositories.custom-behaviour-for-all-repositories

Ответ №6:

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

Комментарии:

1. Это плохой подход. Например, можете ли вы быстро ответить на этот вопрос: сколько менеджеров транзакций будет использоваться для такого смешанного приложения?