【问题标题】:DAO involving a JOIN query涉及 JOIN 查询的 DAO
【发布时间】:2014-07-24 01:46:58
【问题描述】:

我是 DAO 世界的新手。我有 3 张桌子。

  • 消费者
  • 比尔
  • 收据

消费者表包含以下字段

  • consumer_id
  • 消费者姓名
  • 地址

账单表包含

  • bill_number
  • 账单日期
  • consumer_id
  • bill_amount

收据表包含

  • receipt_no
  • 支付日期
  • 已付金额
  • consumer_id

Bill 表与 Consumer 表、Receipt 具有多对一 关系> 表还与 Consumer 表具有 多对一 关系。

目前我已经创建了三个类

  1. 消费者
  2. 比尔
  3. 收据

并为他们创建了 DAO,例如 ConsumerDAO、BillDAO、ReceiptDAO。它们包含基本的 CRUD 操作。

现在我想要一个涉及这三个表中数据的消费者列表。我正在使用 JOIN SQL 查询。如下:

SELECT c.consumer_id,
       c.consumer_name,
       c.address,
       r.receipt_no,
       r.pay_date,
       r.paid_amount,
       b.bill_date,
       b.bill_number,
       b.bill_amount
FROM consumer c
LEFT OUTER JOIN
  (SELECT r.consumer_id,
          r.pay_date,
          r.receipt_number,
          r.paid_amount,
          ROW_NUMBER() OVER (PARTITION BY r.consumer_id
                             ORDER BY r.pay_date) AS rank
   FROM receipt r) r ON (c.consumer_id = r.consumer_id
                         AND r.rank = 1)
LEFT OUTER JOIN
  (SELECT b.consumer_id,
          b.bill_number,
          b.bill_date,
          b.bill_amount,
          ROW_NUMBER() OVER (PARTITION BY b.consumer_id
                             ORDER BY b.bill_date) AS rank
   FROM bill b) b ON (c.consumer_id = b.consumer_id
                      AND b.rank = 1)";

我想知道我应该将这个查询放在哪个 DAO 中?我想在 Consumer 类中添加一个 Bill 字段 和一个 Receipt 字段并在 ConsumerDAO 中添加 getCurrentBillAndReceipt() 方法。这是正确的做法吗?

我阅读了以下问题:

how to create a DAO for join tables

还有更多,但我无法理解。

【问题讨论】:

  • 请记住,虽然这有助于理解这个概念,但有一些像 Avaje Ebean 这样的 ORM 工具会让你的生活变得更轻松。
  • 另外:你能解释一下账单和收据之间的区别吗?我想我知道你要做什么,但我想明确一点。
  • @nmagerko,账单是给消费者的东西,以便他知道他应该支付多少,而收据是存储有关消费者付款信息的东西。
  • 好吧,很酷。由于您的账单和收据与消费者表中的消费者有多对一的关系,我建议您将所有消费者的收据加入消费者类中的Set,并将他/她的所有计入同一类中的Set(这将在您的 DAO 检索消费者时完成)。然后,您可以在 Consumer DAO 中编写一个方法来处理用户的账单和收据(无需冗长、疯狂的 SQL 查询)并返回您需要的内容
  • @nmagerko,正如您从我的 sql 中看到的那样,我必须获取有关消费者最新账单和收据的信息,并且通过使用该 SQL,我可以在单个操作中获取该信息。根据您的回答,我必须为我需要的结果进行多个 SQL 查询。不是吗?

标签: java join dao


【解决方案1】:

如果您的Consumer POJO 变成以下内容,而不是每次您需要访问每个消费者的最新账单/收据时都尝试进行这样的查询:

public class Consumer {
    private Integer consumerId;
    private String consumerName;
    private String address;
    // join data into these variables
    private Set<Bill> bills = new Set<Bill>(0);
    private Set<Receipt> recipts = new Set<Receipt>(0);

    // add constructor and getter/setter methods here
}

那么,在您的ConsumerDAO 中,您的find 方法可能具有以下逻辑:

public class ConsumerDAO {
    /*
     * Find a consumer without any transaction data JOINed in
     */
    public Consumer find(Integer consumerId){
        // create a new Consumer object
        // run SQL query to populate consumerId, consumerName, and address fields of new Consumer object
        // return new Consumer object
    }

    /*
     * Find a consumer with all transaction data JOINed in
     */
    public Consumer findWithTransactionData(Integer consumerId){
        // create new consumer object
        // run a query to get the the basic fields of the Consumer POJO, that also uses
        // JOINs to get all of the consumer's Bills and Receipts; store all of the latter
        // in the Consumer object's Sets
        // return consumer object
    }

    /*** Note that the following two methods could even go in the Consumer class at this point ***/
    public Bill getMostRecentBill(Consumer consumer){
        // iterate through the consumer's bills, and return the most recent one
    }

    public Receipt getMostRecentReceipt(Consumer consumer){
       // iterate through the consumer's receipts, and return the most recent one
    }
}

这是你想要做的吗?我认为将“查找最新”方法放在 Consumer 类本身中是最有意义的,因为这样您就不必将任何东西作为参数传递给该方法;如果您愿意,您可以在从 findWithTransactionData(Integer) 获得的 Consumer 对象上调用 getMostRecentBill()。不过,这通常被认为是一种糟糕的做法,因为 POJO 应该尽可能“愚蠢”。因此,您希望如何处理这取决于您。

【讨论】:

  • 我明白你的意思,但是我对数据库进行了不止一个 SQL 查询,并且必须收集比我必须收集的更多的数据。它不会降低性能吗?
  • 查看我的编辑。当您调用 findWithTransactionData() 时,您确实需要一个 SQL 查询。然后,您将获得所有消费者的账单和收据,而无需每次需要获取最新的账单/收据时都访问数据库。后一部分是你的表现得到提升的地方。
  • 您甚至可能想要添加 findWithBills() 和 findWithReceipts(),在其中您分别只加入账单和收据数据,从而限制您拉回的数据。在代码的其他地方,您调用最适合您需求的“查找”方法
  • 我想我会说:您发布的查询(或某种形式)属于 ConsumerDAO。无论您是想在创建 Consumer 对象时加入所有数据,还是在 DAO 中有一个方法可以根据需要为您获取数据,这实际上取决于您需要多久使用每个用户的数据.如果您需要经常为用户处理账单/收据,我的解决方案效果最好
  • @kaushik 希望对您有所帮助:)
猜你喜欢
  • 2013-04-18
  • 1970-01-01
  • 2016-07-26
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多