问题
I want to use spring data repository interface to execute native queries - I think this way is the simplest because of low complexity.
But when extending interface ex. CrudRepository<T, ID>
I need to write T - my entity, which is not available.
My native queries does not return any concrete entity, so what is the best way to create spring repository without entity?
回答1:
CrudRepository
or JpaRepository
were not designed to work without an <Entity,ID>
pair.
You are better off creating a custom repo, inject EntityManager and query from there:
@Repository
public class CustomNativeRepositoryImpl implements CustomNativeRepository {
@Autowired
private EntityManager entityManager;
@Override
public Object runNativeQuery() {
entityManager.createNativeQuery("myNativeQuery")
.getSingleResult();
}
}
回答2:
Currently there is no functionality in JPA to create repositories with only native or even JPQL queries (using @Query notation). To get around this, you can create a dummy object to insert into the extension interface like below:
@Entity
public class RootEntity {
@Id
private Integer id;
}
@Repository
public interface Repository extends JpaRepository<RootEntity, Integer> {
}
回答3:
You can just annotate your implementation with @Repository
, and get an instance of 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);
}
}
回答4:
I think that using JdbcTemplate can be considered as an alternative when you do not have a concrete entity class for the resultset of a native query. Querying data using JdbcTemplate requires a POJO class for the resultset and a mapper implementing the RowMapper interface for the POJO class.
回答5:
If you are using JPA you need Entities. As previous answers you can create NativeQueries or use Criteria API directly from EntityManager.
Some documentation about custom reports and common repo behaviour:
https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html#repositories.custom-behaviour-for-all-repositories
来源:https://stackoverflow.com/questions/55513776/create-spring-repository-without-entity