Certain scenarios may arise where you need to create a Spring repository without explicitly defining an entity class. While CrudRepository
or JpaRepository
are designed to work in conjunction with an <Entity, ID>
pair, there are workarounds and alternative approaches you can explore.
Option 1: Utilize a Custom Repository
@Repository
public class CustomNativeRepositoryImpl implements CustomNativeRepository {
@Autowired
private EntityManager entityManager;
@Override
public Object runNativeQuery() {
entityManager.createNativeQuery("myNativeQuery")
.getSingleResult();
}
}
Here, you create a custom repository interface CustomNativeRepository
and its implementation CustomNativeRepositoryImpl
. Within the implementation, you can directly inject the EntityManager
and execute native queries using createNativeQuery()
.
Option 2: Implement a Custom Repository with Criteria API
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);
}
}
This approach allows you to define a custom repository interface ProductFilterRepository
and its implementation ProductFilterRepositoryImpl
. Here, you can utilize the Criteria API to construct complex queries without relying on an entity class.