【问题标题】:Select data from another table from JPA repository从 JPA 存储库的另一个表中选择数据
【发布时间】:2019-11-17 11:33:30
【问题描述】:

我在 JPA 存储库中有这个查询:

@Repository
public interface PaymentTransactionsDailyFactsRepository extends JpaRepository<PaymentTransactionsDailyFacts, Integer> {

    @Query(value = "SELECT " + 
            " COUNT(*) count, " + 
            " SUM(amount) volume, " + 
            " DATE(created_at) date, " + 
            " YEAR(created_at) year, " + 
            " MONTH(created_at) month, " + 
            " WEEK(created_at) week, " + 
            " DAY(created_at) day, " + 
            " type transaction_type, " + 
            " contract_id, merchant_id, terminal_id, " + 
            " status, card_brand, currency " + 
            " FROM payment_transactions " + 
            " WHERE status NOT IN ('pending_async','pending','pending_review','in_progress','new') AND created_at BETWEEN :start_date AND :end_date " + 
            " GROUP by date, contract_id, merchant_id, terminal_id, transaction_type, status, card_brand, currency", nativeQuery = true)
    List<PaymentTransactionsDailyFacts> generateDailyFacts(@Param("start_date") LocalDate start_date, @Param("end_date") LocalDate end_date);
}

但是当我在 Spring Scheduler 中执行它时出现错误:

SQL Error: 1054, SQLState: 42S22
Caused by: java.sql.SQLSyntaxErrorException: No such column: id

当我在 MariaDB 中执行此查询时,它工作正常:

SELECT  COUNT(*) count,  SUM(amount) volume,  DATE(created_at) date,  YEAR(created_at) year,  MONTH(created_at) month,  WEEK(created_at) week,  DAY(created_at) day,  type transaction_type,  contract_id, merchant_id, terminal_id,  status, card_brand, currency  FROM payment_transactions  WHERE status NOT IN ('pending_async','pending','pending_review','in_progress','new') AND created_at BETWEEN '2011-04-11 00:00:01' AND '2029-04-11 00:00:00'  GROUP by date, contract_id, merchant_id, terminal_id, transaction_type, status, card_brand, currency

如您所见,我正在为表 payment_transactions 运行此本机查询,但我期待表 payment_transactions_daily_facts 的结果。有没有办法正确实现这个查询?

【问题讨论】:

  • 数据库表payment_transactions中是否有id列。当您直接在 mariadb 中执行查询时,它会向您显示结果集,因为您不要求返回 id 列。但是,在您的 spring-data 应用程序中,它应该构建 PaymentTransactionsDailyFacts 实体,这些实体似乎具有名为 id 的属性。如果您发布实体定义和表定义,我们将能够检查那里有什么问题。
  • 我猜你的 PaymentTransactionsDailyFacts 也有一个 ID。如果是这种情况,您还需要从本机脚本中获取 Id
  • 顺便说一句,我不得不问这是你解释错误的标志。应该清楚您的PaymentTransactionsDailyFacts 的代码将需要解决您的问题。
  • 也许你可以分享你的PaymentTransactionsDailyFacts实体

标签: spring spring-boot spring-data-jpa mariadb jpa-2.0


【解决方案1】:

尝试在查询中添加id

@Query(value = "SELECT " + 
            " id," + 
            " COUNT(*) count, " + 
            " SUM(amount) volume, " + 
            " DATE(created_at) date, " + 
            " YEAR(created_at) year, " + 
            " MONTH(created_at) month, " + 
            " WEEK(created_at) week, " + 
            " DAY(created_at) day, " + 
            " type transaction_type, " + 
            " contract_id, merchant_id, terminal_id, " + 
            " status, card_brand, currency " + 
            " FROM payment_transactions " + 
            " WHERE status NOT IN ('pending_async','pending','pending_review','in_progress','new') AND created_at BETWEEN :start_date AND :end_date " + 
            " GROUP by date, contract_id, merchant_id, terminal_id, transaction_type, status, card_brand, currency", nativeQuery = true)
    List<PaymentTransactionsDailyFacts> generateDailyFacts(@Param("start_date") LocalDate start_date, @Param("end_date") LocalDate end_date);

【讨论】:

    【解决方案2】:

    如果您想获取所有PaymentTransactionsDailyFacts 实体,它们介于给定的start_dateend_date 之间,并且它们的status 不是 ('pending_async','pending','pending_review','in_progress', 'new'),您可以使用以下查询。

    @Query(value = "SELECT * " 
                " FROM payment_transactions " + 
                " WHERE status NOT IN ('pending_async','pending','pending_review','in_progress','new') AND created_at BETWEEN :start_date AND :end_date " + 
                " GROUP by date, contract_id, merchant_id, terminal_id, transaction_type, status, card_brand, currency", nativeQuery = true)
    

    但是,由于您在查询中使用了group by,因此您似乎正在尝试获取一些聚合数据,而不仅仅是满足条件的PaymentTransactionsDailyFacts 实体列表。 如果是这样,那你就做错了。您必须使用投影

    这里有一个关于如何使用 spring 数据投影的快速教程。 https://www.baeldung.com/spring-data-jpa-projections

    或。你可以在这里阅读官方文档。 https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections

    更新:使用投影

    1. 首先在项目的某处创建一个如下所示的界面。您应该根据需要调整返回类型。

      public interface PtdsDTO {
          Integer getCount();
          BigDecimal getVolume();
          LocalDate getDate();
          Short getYear();
          Short getMonth();
          Short getWeek();
          Short getDay();
          String getTransactionType();
          Integer getContactId();
          Integer getMerchantId();
          Integer getTerminalId();
          String getStatus();
          String getCardBrand();
          String getCurrency();
      }
      
    2. 然后,将该接口导入相应存储库的顶部。

    3. 将存储库的返回类型更改为List&lt;PtdsDTO&gt;

      List<PtdsDTO> generateDailyFacts(@Param("start_date") LocalDate start_date, @Param("end_date") LocalDate end_date);
      

    就是这样。

    【讨论】:

    • 你能给我看一下带有投影的代码示例吗
    猜你喜欢
    • 2021-09-24
    • 2013-10-15
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 2021-12-30
    相关资源
    最近更新 更多