我有一个简单的java对象
public class Order {
private int quantity;
private long price;
private long totalPrice;
}
我只存储数量和价格,根据数量*价格生成totalprice字段。
现在我在order类中有了一个名为populatetotalprice()的方法。但我似乎把一个逻辑放在一个实体类中,这个实体类可能是反模式的?
我的另一个选择是使用helper静态方法。
这种行为的最佳实践是什么?
4条答案
按热度按时间rfbsl7qr1#
有一个
totalPrice
实体中的字段,其中值是其他字段值的函数,与数据库的非规范化思想密切相关(从您对其他答案所做的一些评论来看,我推测您使用的是这个实体以及您要查询的备份数据库表。)特别是,它违反了3nf:列值应仅依赖于键列值。尽管存储计算值违反了3nf,但有时这样做有很好的性能原因。与数据库一样,处理这类需求有多种方法。您也许可以将问题转移到数据库并消除
totalPrice
java对象中的字段。根据所使用的dbms,一种可能性是将数据库模式定义为具有计算列(计算列不是标准的sql,但有几个系统(如microsoft的sql server)支持它们SELECT
存储在数据库中并像查询另一个表一样进行查询的语句)。视图可能类似于:然后您的代码就可以查询
orders_view
而不是orders
当需要使用时totalPrice
(或total_price
).最后,您可以在执行过程中对实体进行反规范化,并接受结果,主要结果是更新异常:您更新了
price
和/或quantity
但未能更新totalPrice
现场。您可以通过更新totalPrice
在setters forquantity
以及price
(而不是有一个单独的populateTotalPrice()
方法):请注意,没有为
totalPrice
. 以这种方式安排代码可以确保您不会因为忽略对的调用而遇到问题populateTotalPrice()
. (当然,如果您可以在不经过java对象的情况下更改数据库值,那么最终仍然会出现更新异常。)在某些框架中,每次从表中加载实体时都可以进行这些计算(例如,hibernate
postLoad
使用android room,您可以使用LiveData
字段)那么您根本不需要在表中存储字段。关于这个问题的进一步解读:
第三范式与计算值
计算列是否打破3nf(第三范式)?
数据库规范化-谁说得对?
x6492ojm2#
永远不要使用静态方法!!静态方法是邪恶的!!
以下是一些选项:
使用calculateprice(order…)方法创建orderservice。您可以使用ioc容器和控制反转在需要的地方注入此服务(如spring、guice等)
每次调用order.gettotalprice()时计算总价,而不是存储/设置totalprice。
在order(…)构造函数中传递数量和价格,并在构造函数中计算totalprice。在这种情况下,order类中的所有字段都是final。而你只有能手(没有二传手)。然后类将是不可变的
llmtgqce3#
是的,您不必在订单中输入总价来创建发票。
在创建发票的过程中计算总价。
f1tvaqid4#
java实践是用属性而不是字段来处理对象。大多数属性都基于backing字段,但在您的情况下,它对属性是有意义的
totalPrice
作为计算属性: