我正在尝试设计一个非常简单的应用程序,并且让自己对Hibernate对实体和值对象的定义感到困惑(如Java Persistence with Hibernate的第4章中所定义)。
我拥有的是一个可以与客户合作的应用程序,可以下订单(一对多关系)。这些订单中的每一个都有许多订单行(也是一对多)。现在,我认为客户有身份(客户编号),订单(订单编号)也是如此,因此他们是实体对象?我的困惑在于订单行。
订单行包含数量,产品编号和价格。如果订单行没有它的顺序就不能存在,并且它没有自己的标识,因此我将其视为一个值对象。但我不能将订单行作为订单表的一部分,因为订单与订单行之间存在一对多的关系。一对多关系如何与值对象的定义一起使用?来自Hibernate的书:
“值类型的对象没有数据库标识;它属于实体实例,其持久状态嵌入在拥有实体的表行中。值类型没有标识符或标识符属性”
如果有人能解决我的困惑,我会非常感激:)
答案 0 :(得分:6)
Hibernate的文档区分了实体类型和值类型,而不是值对象。
- 实体类型对象:具有自己的数据库标识
- 值类型对象:属于实体,其持久状态嵌入在拥有实体的表行中。值类型没有标识符或标识符属性。
据我所知,本书使用一个样本,address
表示为单个字符串和user
对象,其中包含一个地址字符串:
实现为值类型(通常表示数据库级别的同一个表中的列),如果删除了用户,则其地址也是如此。如果没有用户,该地址将无法生效,无法共享。
作为实体类型(可能意味着使用单独的表)实现,地址将独立存在而无需用户,两个用户可以共享相同的地址。
在您的情况下,订单行不属于订单,其持久状态未嵌入订单行(没有意义),它有自己的标识(由orderId和productId组成) 。订单行绝对不是值类型,它是实体类型。
实际上,只要你在关联(一对一,一对多等)方面思考,你肯定会操纵实体。
答案 1 :(得分:1)
我认为你所拥有的是一个相当通用的ORM问题。
您提到“如果没有订单,订单行就不能存在,并且没有自己的”。
好吧,虽然OrderLine不能与订单一起存在,但并不意味着它不能拥有一个身份。
拿到您的订单实体,没有客户就不能存在,但您已经将其视为实体,是吗?
所以,这是对实体的建议:
- 客户(可以没有或多个订单实体)
- 订单(可以有一个或多个OrderLine实体)
- OrderLine
答案 2 :(得分:1)
我认为你正在寻找复合元素。实际上使用Order和purchaseItems(订单行)的参考中有一个例子。当Hibernate说它无法独立时,并不意味着它不能拥有自己的表,只是它总是与父元素相关联:
<class name="eg.Order" .... >
....
<set name="purchasedItems" table="purchase_items" lazy="true">
<key column="order_id"/>
<composite-element class="eg.Purchase">
<property name="purchaseDate"/>
<property name="price"/>
<property name="quantity"/>
<many-to-one name="item" class="eg.Item"/>
</composite-element>
</set>
</class>
答案 3 :(得分:0)
value object是一个小对象,表示一个简单的实体,它的相等性不是基于同一性:即当两个值对象具有相同的值时,它们是相等的,不一定是相同的对象
答案 4 :(得分:0)
您可以通过一对一映射以及一对多映射来支持订单行作为值类型和值类型。 显然,Java Collections用于映射value类型与entity的* -to-many关系.Inside合适的collection,element和composite-element按需使用,如下所述: 对于实体和值类型(非JDK类型)之间的一对多关系,使用复合元素。 对于一对多关系,其中值类型表包含JDK类型的单个属性(比如字符串),使用元素。 这个概念在使用Hibernate的Java持久性的第6章中给出。 有关详细信息,请参阅此链接 https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/components.html