来自非实体对象的 REST 端点

Posted

技术标签:

【中文标题】来自非实体对象的 REST 端点【英文标题】:REST Endpoint from non-entity object 【发布时间】:2019-09-11 14:09:28 【问题描述】:

Spring 新手 - 我想要一个 REST 端点来公开 SQL 查询的结果。 Amount 类不是@Entity,而是另一个表中的一些字段。我可以将其声明为@Entity,但随后 Spring Data 将为 Amount 创建一个我不想要的表。但是没有@Entity,Spring 会抱怨:

java.lang.IllegalArgumentException: Not a managed type: interface com.swed.fuelcounter.entities.Amount

下面的代码对我来说很好,但我不需要金额实体,没有它我该怎么办?

服务类:

@RestController
@RequestMapping(value = "/rest")
class AmountsService 
    private final AmountRepository repository;

    public AmountsService(AmountRepository repository) 
        this.repository = repository;
    



    @RequestMapping(value = "/id/amount-by-month", method = RequestMethod.GET)
    public ResponseEntity<List<AmountInterface>> getAmountByMonth(@PathVariable("id") int id) 
        List<Amount> amounts = repository.sumAmountByDateAndDriver(id);
        return new ResponseEntity<>(amounts, HttpStatus.OK);
    

量POJO类:

public class Amount 

    public Amount(double amount, Date date)
        this.amount = amount;
        this.date = date;
    


    @Getter
    @Setter
    private double amount;

    @Getter
    @Setter
    private Date date;

Repository 接口和 RepositoryImpl 类:

public interface AmountRepository extends JpaRepository<Amount, Long> 

    List<Amount> sumAmountByDateAndDriver(int id);


@Component
public class AmountRepositoryImpl 

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private AmountRepository repository;

    @SuppressWarnings("unused")
    public List<Amount> sumAmountByDateAndDriver(int id) 
        String hql = "SELECT NEW Amount(Sum(price*volume) as amount, date) FROM record WHERE id = :id GROUP BY date";
        TypedQuery<Amount> query = entityManager.createQuery(hql, Amount.class);
        query.setParameter("id", id);
        return query.getResultList();
    


【问题讨论】:

如果 Amount 不是 JPA 实体,则不能为其使用 Spring Data JPA 接口(即不能扩展 JpaRepository)。此外,您可能希望您的 Impl 类实现接口,不是吗?因为使用您当前的代码,您的 Impl 类在任何地方都无法使用。 Spring 使用 Impl 类来运行方法。如果我不应该使用 JPA,你能提示我应该使用什么吗? 你在哪里使用它? AmountRepositoryImpl 没有实现 AmountRepository,所以不会注入 AmountsService 无论如何我都不是 Spring 专家,但我知道 @Component 注释应该进行注入,并且在我的代码中也是如此。无论如何,我找到了一个解决方案 - JPA Projection 【参考方案1】:

在我的例子中,我们将实体设为不可变,如下所示。因此将数据库结果存储在 Amount 对象中。

@Entity
@Immutable
@Getter
public class Amount 

   public Amount(double amount, Date date)
      this.amount = amount;
      this.date = date;
   

   /* The No-Args Constructor is needed for Hibernate */
   public Amount()  

   @Column
   private double amount;

   @Column
   private Date date;

【讨论】:

以上是关于来自非实体对象的 REST 端点的主要内容,如果未能解决你的问题,请参考以下文章

如何在 REST 端点中发布具有关系的实体 - Kotlin Spring Data

Spring Rest API 验证应该在 DTO 中还是在实体中?

SpringBoot 中的 Rest 服务需要来自 GET 请求的 JSON 中的嵌套对象

CoreData & RestKit - 从多个来源获取相同的实体类型

Spring Data Rest 中同一实体的多个存储库

具有非实体参数的 JPA 标准构造