1

次のように製品の価格設定を実装したいと考えています。

  • Product オブジェクトは、現在の価格を表す単一の Pricing オブジェクトを保持します。
  • Product テーブルは、1 対多の関係で Pricing テーブルにリンクされています
+------------+ +---------------------+
| | 製品 | | | 価格 |
+------------+ 1-n +---------------------+
| | 商品ID | ----------- | 商品ID |
| | ... | | | price_id |
+------------+ | 価格_値 |
                           | | price_creation_time |
                           | | ... |
                           +---------------------+

これまでのところ単純に聞こえますが、私が問題を抱えている部分は

  • 製品には、1 つの有効な価格、つまり最新の価格しかありません。
  • 最新のものより前の価格設定レコードは取得しないでください。
  • ユーザーが製品の価格設定を編集するとき、現在のレコードは更新されるべきではなく、代わりに現在のタイムスタンプを持つ新しいレコードが挿入されるべきです。
  • 以前の価格記録は、履歴上の理由 (顧客が購入時に製品に対して支払った払い戻しを希望するなど) のために保持されます。

基本的に、製品オブジェクト内からは、関係は 1 対 1 の関係であるかのように見える必要があります。ただし、Hibernateを使用してそのようなことを実装する方法がわかりません

1 対多の関係の最後のレコード Hibernate Criteriaは、Criteria と呼ばれるものが役立つ可能性があることを示唆していますが、私は Hibernate の経験がほとんどなく、まだクラス アノテーションを理解しています。

Hibernate とのこのような 1 対 1 の関係のように見えるような 1 対多の関係を実装することは可能ですか? どうすればそれを行うことができますか?

更新: アイデアに関するもう少し詳しい情報は次のとおりです。

領収書は、購入した各アイテムのレコードのコレクションで構成されます。

+--------------+ +------------------+
| | 領収書 | | | 領収書明細 | +---------+
+--------------+ +------------------+ +----- | 製品 |
| | レシート ID | ----------- | レシート ID | | | +---------+
| | 受領時刻 | | | 商品ID | ---+ +-------+
| | ... | | | price_id | ----------- | 価格 |
+--------------------+ | 商品の数量 | +------+
                             | | ... |
                             +------------------+

製品には、最新のタイムスタンプを持つ価格テーブルの価格レコードによって決定される現在の価格 (明らかに 1 つの現在の価格のみ) があります。

SELECT *
FROM prices
WHERE product_id = (Product ID goes here)
ORDER BY price_creation_time;
LIMIT 1;

価格を更新するとき、現在製品に関連付けられている価格レコードを更新するのではなく、新しい価格レコードを挿入したい.

INSERT INTO price (
    product_id, 
    price_value, 
    price_creation_time
) VALUES (
    (Product ID goes here),
    (New price goes here),
    NOW()
);

顧客が何かを購入すると、購入した各アイテムのレシート レコードに行が追加されます。各行は製品の ID で構成され、cut には、領収書が生成された時点で適用可能な価格設定レコードの ID も含まれています。そうすれば、購入時に顧客が製品に支払った金額がわかります。

このデータは、まだ定義されていない会計やその他のデータ マイニング アクティビティにも使用できます。

4

3 に答える 3

0

実際には、PRODUCT -> PRODUCT_PRICE からの明示的な FK を使用するのが最善の解決策です。

優先:

<one-to-one name='currentPrice' class='ProductPrice' column='FK_CURR_PRICE' 
    fetch='join' />

a 内に a をマップして、最新の価格の ID をサブ選択できますが、同時実行に関してはパフォーマンスが高くなく、堅牢でもありません。

間接的、好ましくない:

<one-to-one name='currentPrice' class='ProductPrice'>
    <formula>
        (select MAX(ID) from PRODUCT_PRICE where PRODUCT_PRICE.FK_PRODUCT=this.ID)
    </formula>
</one-to-one>
于 2013-09-08T11:37:17.763 に答える
0

ゆっくりと変化するディメンションを調べる必要があると思います。

http://en.wikipedia.org/wiki/Slowly_changeing_dimension

このスレッドも興味深いと思うかもしれません。なぜなら、それはあなたがしていることと非常に相関しており、私が自分自身に尋ねたときと同じような状況に陥ることはほぼ確実だからです。

ひねりを加えたテンポラル データベース設計 (ライブ vs ドラフト行)

当時の私自身の発見を要約しようとすると(私の質問はブログ関連として紹介しましたが、ショッピングソフトウェアも設計していました):

  1. 現在の行と過去の行を効率的にクエリするための最良の手段 (imho) は、後者を別の監査テーブル (つまり、price と price_revs) に格納することです。これにより、見栄えが悪く非効率的なクエリを回避し、顧客向けのユースケースで物事を迅速かつ合理的に保つことができます.

    監査テーブルは、必要に応じて更新する必要があります。理想的には、必ずしもトリガーを使用する必要はありません。(念のために言っておきますが、私は最終的に、2 つの別個の start_date/created_at および end_date/deleted_at フィールドではなく、tsrange 型を選択しました。)

  2. 特にカスケード削除を導入する場合は、過度に熱心な外部キー制約に注意してください。製品を削除しても、製品とその価格履歴を残しておきたい場合があります。その場合は、削除済みのステータスまたはフラグ、または選択したものが必要です。ある意味で、主な参照ポイントは、product_id や price_id ではなく、リビジョン ID であるべきです。

  3. 同じ製品の最新の非ライブ行とライブ行を共存させたい場合 (たとえば、提案されたドラフト価格がランダムマネージャーによって検証されている間にライブ価格を設定する場合)、より良い解決策は次のとおりであることがわかりました。別の価格 (ドラフト ステータス) をまとめて作成します。必要がなくなったときにライブ ブランチにマージされる (つまり、「現在の」行から削除される) gitのような新しい「現在の」ドラフト ブランチと考えてください。

于 2013-09-08T12:23:11.600 に答える