Java 关于数据建模的非常基本的问题
假设我必须用Java为Java 关于数据建模的非常基本的问题,java,oop,data-modeling,Java,Oop,Data Modeling,假设我必须用Java为订单开发一个简单的数据模型,其中包含订单项。看起来Order应该包含对集合的引用Order Items现在如果Order和Order Items存储在数据库中怎么办?Order是否仍保留对集合的引用,或者只提供一个简单的函数retrieveItemsByOrderId 现在,如果订单和订单项存储在数据库中会怎么样?订单是否仍保留对集合的引用,或者只提供一个简单的函数retrieveItemsByOrderId 这取决于持久层如何使用对象模型将类映射到数据库表。如果您使用的是
订单
开发一个简单的数据模型,其中包含订单项
。看起来Order
应该包含对集合的引用Order Items
现在如果Order
和Order Items
存储在数据库中怎么办?Order
是否仍保留对集合的引用,或者只提供一个简单的函数retrieveItemsByOrderId
现在,如果订单和订单项存储在数据库中会怎么样?订单是否仍保留对集合的引用,或者只提供一个简单的函数retrieveItemsByOrderId
这取决于持久层如何使用对象模型将类映射到数据库表。如果您使用的是Hibernate/JPA/EclipseLink/Toplink或类似的ORM框架,那么在Order
类中只有一个getter方法,它将返回OrderItem
实例的集合。部分代码表示为:
class Order
{
private long id;
private Set<OrderItem> orderItems;
...
public Set<OrderItem> getOrderItems()
{
return orderItems;
}
public void setOrderItems(Set<OrderItem> orderItems)
{
this.orderItems = orderItems;
}
}
class OrderItem
{
private Order order;
...
public Order getOrder()
{
return order;
}
public void setOrder(Order order)
{
this.order = order;
}
}
类顺序
{
私人长id;
私人设置订单项;
...
公共集getOrderItems()
{
退货订单项目;
}
公共无效setOrderItems(集合orderItems)
{
this.orderItems=orderItems;
}
}
类OrderItem
{
私人秩序;
...
公共秩序
{
退货单;
}
公共无效订单(订单)
{
这个。顺序=顺序;
}
}
我还没有列出框架使用的所有注释,包括每个实体类的键,但是您需要这样做才能使事情正常工作。然而,要点是:
类的每个实例都包含Id,Id可以是自然键(也可以是生成的键)Order
- 调用
方法将导致getOrderItems
与要返回的订单关联的订单项。请注意,大多数ORM都会延迟获取集合,因此您需要了解更多的概念,如使用托管和分离实体来实际实现这一点;您可能需要编写一个应用程序服务来完成合并分离实体的工作,然后获取集合Set
OrderItem
类中引用Order
。这将导致单向关系而不是双向关系。可以在大多数ORM框架中使用单向关系,但考虑以下内容:
- 维护单向关系的引用完整性(使用外键)不是件小事;这取决于您的ORM框架。一些ORM框架可能允许您在不做任何进一步工作的情况下,不从
引用OrderItem
,而其他框架可能要求您使用联接表。如果要在数据库中持久化对象图,则必须知道哪个Order
映射到OrderItem
;通过从顺序
中删除引用,您将被迫将此信息映射到其他位置,映射到不同的实体中,通常会生成不同的表;这是前面提到的联接表订单项
- 单向关系对于大多数用途来说已经足够了。如果
负责访问订单
实例,则不需要双向关系。但是如果您发现自己需要访问订单项
的OrderItem
,那么您将需要一个双向关系。我建议您阅读,这样无论在这种情况下对Order
或Order
类执行任何变异操作,您都能够保持引用完整性。如果没有这种模式,您几乎总是会发现自己看到模糊、无法解释和不正确的对象图,从而导致数据库状态不一致OrderItem
如果您没有使用ORM或不打算使用ORM,那么这将取决于您正在访问
OrderItem
实例;简而言之,这取决于您如何编写持久层。如果您使用的是DAO模式,那么将一个新方法retrieveItemsByOrderId
添加到DAO接口就是解决方案。我认为您应该在Order模型类中保留对OrderItem集合的引用。然后,您可以实现getOrderItems()方法,该方法基于订单id从数据库检索项目
仅当您需要访问订单项(搜索延迟加载)时才应执行此查询,而不是每次从DB加载订单实体时都应执行此查询
在Order model类中使用对OrderItem集合的引用将利用您的应用程序,以防您需要在同一请求-响应流中访问两次订单项
getOrderItems()方法的框架如下所示:
public List<OrderItem> getOrderItems(){
if(this.orderItems==null)
// perform the query
// set the this.orderItems values
}
return this.orderItems
}
公共列表getOrderItems(){
if(this.orderItems==null)
//执行查询
//设置this.orderItems值
}
返回此文件。orderItems
}
类
OrderItem
中的属性order
不应该是必需的,因为它在order
和OrderItem
之间引入了循环依赖关系。只有当需要从给定项目导航到某个顺序时,才有意义。@home,您是对的,只是使用相互注册模式在这两个项目中注册引用几乎总是更好的。此外,我认为OrderItem或框架不会很好地适应您的建议,特别是如果您在OrderItem上维护了外键。+1,这一点很好。顺便说一句:我只定义了单向关系(至少在“简单”模型中是这样),从来没有遇到过问题。但正如我之前提到的,这在很大程度上取决于国防部的复杂性