java - 选择最近的相关记录

标签 java hibernate postgresql

我想按如下方式为产品实现定价:

  • Product 对象包含一个描述其当前价格的 Pricing 对象。
  • Product 表以一对多关系链接到 Pricing 表
+------------+             +---------------------+
| Product    |             | Price               |
+------------+     1-n     +---------------------+
| product_id | ----------- | product_id          |
| ...        |             | price_id            |
+------------+             | price_value         |
                           | price_creation_time |
                           | ...                 |
                           +---------------------+

Sounds simple enough so far, but the part I'm having trouble with is

  • The Product has only one active Price, namely the most recent one.
  • Any pricing records prior to the most recent one shouldn't be fetched.
  • When the user edits a product's pricing, the current record should not be updated, a new one with a current timestamp should be inserted instead.
  • The previous pricing records are kept for historical reasons (such as seeing what a customer wanting a refund paid for the product at the time of purchase).

Essentially, from within the Product object, the relationship should appear as if it was a one-to-one relationship. However, I don't know how to implement such a thing using Hibernate

Last Record of one to many relation Hibernate Criteria suggests something called Criteria may be of help, but I have very little Hibernate experience and am still getting to grips with the class annotation.

Is it possible to implement a one-to-many relationship such that is appears to be a one-to-one relationship like this with Hibernate? How would I go about doing it?

UPDATE: A bit more info on the idea is as follows:

A receipt will consist of a collection of records for each item bought.

+--------------+             +------------------+
| Receipt      |             | ReceiptLine      |             +---------+
+--------------+             +------------------+      +----- | Product |
| receipt_id   | ----------- | receipt_id       |      |      +---------+
| receipt_time |             | product_id       | -----+      +-------+
| ...          |             | price_id         | ----------- | Price |
+--------------+             | product_quantity |             +-------+
                             | ...              |
                             +------------------+

Products have a current price (and obviously only one current price) which is determined by the price record in the price table that has the most recent timestampe.

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。这样我就可以知道客户在购买产品时支付了多少费用。

此数据还可用于尚未定义的会计和其他数据挖掘 Activity 。

最佳答案

  • The Product has only one active Price, namely the most recent one.
  • Any pricing records prior to the most recent one shouldn't be fetched.

您可以使用 Hibernate filters 来实现此目的.这将允许您在不初始化整个集合的情况下检索集合的某些元素。在这种情况下,您只想获取一个 Price来自 price collection 的元素(最近的一个)出现在你的Product类(class)。

将此过滤器定义添加到您的 Product映射文件(首先使用 <filter-def/> 元素中的 <hibernate-mapping/> 元素定义过滤器,然后将过滤器附加到 price 集合):

 <hibernate-mapping package="x.y.z">
 <class name="Product" table="product_table_name">
 ....
 <set name="priceList" inverse="true" cascade="save-update" lazy="true">
 ...
 <filter name="priceFilter"
            condition="price_id = (select max(p.price_id) from Price p where 
            p.product_id = product_id)" />
 </set>
 </class>
 <filter-def name="priceFilter"/>
 </hibernate-mapping>

此过滤器将加载 price max(price_id) 是最近为 product 添加的价格.现在您需要为给定 session 启用此过滤器,可以按如下方式完成:

session.enableFilter("priceFilter");

为了确保向您提供 Product与最近相关Price ,在检索产品数据之前在 session 中启用过滤器:

session.enableFilter("priceFilter");
Criteria criteria = session.createCriteria(Product.class);
criteria.setFetchMode("priceList", FetchMode.JOIN);
criteria.add(Restrictions.eq("id", productId));
Product product = (Product) criteria.uniqueResult();

使用此过滤器,关系将显示为一对一关系。关联的价目表将仅包含一个 Price (最近的一个)。如果您不使用 session.enableFilter("stateFilter") 启用过滤器, Hibernate 将加载所有关联的价格。

  • When the user edits a product's pricing, the current record should not be updated, a new one with a current timestamp should be inserted instead.
  • The previous pricing records are kept for historical reasons (such as seeing what a customer wanting a refund paid for the product at the time of purchase).

假设您有一个 setprices与特定 product 相关联,这可以通过以下方式方便地完成 updatePrice Product 中的方法类:

private Set<Price> priceList = new HashSet<Price>();
...
public void updatePrice(Price price) {
price.setId(null);// Hibernate will execute an INSERT statement

price.setProduct(this);
priceList.add(price);
}

想法是设置Id Price的属性(property)至 null在添加更新的 price 之前到 priceListproduct .

如果您向价目表添加一个新价格,这个新价格将根据“按可达性持久化”变得持久化。当原始实例变为持久实例时或就在内存中状态与数据存储同步之前,从持久实例可访问的所有对象都变为持久实例。

关于java - 选择最近的相关记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18681905/

相关文章:

java - 同时为许多用户提供更好的性能

java - JPA @版本 : how to use it?

postgresql - 更新表中的多个字段

sql - 过滤对具有多个值的 crosstab() 查询结果的意外影响

javascript - 从 promise 导出数组,但在另一个文件需要时不加载?

java - 如何为 JLabel 创建事件处理程序?

java - javac 是否优化目标文件(*.class)?

java - 如何在 Java 中在 Y 线程上运行 X 任务?

java - JCE:验证 X509 自签名证书时出现异常

java - 我可以在可区分实体层次结构的子类上使用 CompositeId 吗?