创建没有实体的spring存储库

Posted

技术标签:

【中文标题】创建没有实体的spring存储库【英文标题】:Create spring repository without entity 【发布时间】:2019-08-26 01:57:45 【问题描述】:

我想使用spring数据存储库接口来执行原生查询-我认为这种方式是最简单的,因为复杂度低。

但是在扩展接口时。 CrudRepository<T, ID> 我需要写 T - 我的实体,它不可用。

我的本​​机查询不返回任何具体实体,那么在没有实体的情况下创建 spring 存储库的最佳方法是什么?

【问题讨论】:

【参考方案1】:

CrudRepositoryJpaRepository 无法在没有 <Entity,ID> 对的情况下工作。

你最好创建一个自定义仓库,注入 EntityManager 并从那里查询:

  @Repository
  public class CustomNativeRepositoryImpl implements CustomNativeRepository 

    @Autowired
    private EntityManager entityManager;

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

【讨论】:

这不是完整的代码。什么是CustomNativeRepository,你如何定义它? 在这种情况下只是一个具有公共 Object runNativeQuery() 方法的接口 为了完整性添加那个简单的sn-p会更好 或者更好的是,没有接口。 虽然这个答案似乎是正确的,但我不明白为什么 Spring 不允许在其上使用 @Repository 和在方法上使用 @Query 的接口。【参考方案2】:

您可以只使用@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);
    

【讨论】:

【参考方案3】:

如果您使用 JPA,则需要实体。作为之前的答案,您可以直接从 EntityManager 创建 NativeQueries 或使用 Criteria API。

一些关于自定义报告和常见回购行为的文档:

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

【讨论】:

【参考方案4】:

目前,JPA 中没有创建仅包含本机或 JPQL/HQL 查询的存储库的功能(使用 @Query 表示法)。为了解决这个问题,您可以创建一个虚拟对象以插入到扩展接口中,如下所示:

@Entity
public class RootEntity 
    @Id
    private Integer id;


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

【讨论】:

这是一些奇怪的代码。它甚至不会编译。接口上的私有修饰符?好吧,也许这是一个错字。但是即使将接口更改为类也不会让您的 Spring 应用程序运行。 是的,这是一个错字,现在应该可以了。如果您遇到问题,您能否提供错误消息,或打开另一个问题?【参考方案5】:

我认为,当您没有用于本机查询结果集的具体实体类时,可以考虑使用 JdbcTemplate 作为替代方案。使用 JdbcTemplate 查询数据需要一个用于结果集的 POJO 类和一个为 POJO 类实现 RowMapper 接口的映射器。

【讨论】:

这是一种不好的方法。例如,您能否快速回答这个问题:这样的混合应用程序将使用多少个事务管理器?【参考方案6】:

这对我们有用。见实体管理器

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()
        ...
    


顺便说一句,我认为这里甚至不需要 @Repository 注释。

【讨论】:

以上是关于创建没有实体的spring存储库的主要内容,如果未能解决你的问题,请参考以下文章

我需要为哪些实体创建 Spring Data 存储库?

在 Java 或 Grails 应用程序中动态创建实体、Spring 存储库和 facelets 页面

在 Spring Data JPA 中,如何在运行时添加实体?

删除分离实体spring jpa Repository接口

@Primary 等效于自动装配的 Spring JPA 存储库

如何使用 Spring/Hibernate 创建数据库?