Michael
Michael

Reputation: 42050

Very basic question about data modeling

Suppose I have to develop a simple data model in Java for Order, which contains Order Items. It looks like Order should hold a reference to a collection Order Items Now what if Order and Order Items are stored in a database? Should the Order still hold a reference to the collection or just a simple function retrieveItemsByOrderId should be provided instead?

Upvotes: 1

Views: 7277

Answers (2)

Fabrizio D'Ammassa
Fabrizio D'Ammassa

Reputation: 4769

I think you should keep a reference to OrderItem collection in your Order model class. Then, you could implement the method getOrderItems() that retrieves the items from the db based on the order id.

This query should be performed only if you need to access the order items (search for LAZY LOADING) and not every time you load the Order entity from DB.

Using a reference to OrderItem collection in your Order model class will leverage your application in case you need to access twice the order items in the same request-response flow.

A skeleton of getOrderItems() method would be like this:

public List<OrderItem> getOrderItems(){
    if(this.orderItems==null)
        // perform the query
        // set the this.orderItems values
    }
    return this.orderItems
}

Upvotes: 1

Vineet Reynolds
Vineet Reynolds

Reputation: 76709

Now what if Order and Order Items are stored in a database? Should the Order still hold a reference to the collection or just a simple function retrieveItemsByOrderId should be provided instead?

This would depend on how your object model is used by the persistence layer to map classes to the database tables. If you are using Hibernate/JPA/EclipseLink/Toplink or a similar ORM framework, you would merely have a getter method in your Order class that would return the collection of OrderItem instances. Partial code representation would be:

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;
    }
}

I haven't listed all annotations in use by the frameworks, including the keys for each entity class, but you'll need to do this to get things working. The salient points however are:

  • each instance of an Order class contains the Id, which may be the natural key (or may be a generated one).
  • invoking the getOrderItems method will result in the Set of order items associated with an order to be returned. Note that most ORMs will lazily fetch collections, so you'll need to understand a few more concepts like working with managed and detached entities to actually get this to work; you might need to write an application service to do the work of merging detached entities and then fetch the collection.

One of the comments stated that there is no need to reference the Order from the OrderItem class. This would lead to a unidirectional relationship instead of a bidirectional one. You can use unidirectional relationships in most ORM frameworks, but consider the following:

  • It would not be trivial to maintain referential integrity (using foreign keys) for unidirectional relationships; this would depend on your ORM framework. Some ORM frameworks might allow you to not have a reference to Order from OrderItem without any further effort on your part, while others might require you to use a Join table. If you are persisting an object graph in the database, then it is imperative to know which OrderItem maps to an Order; by removing the reference from the OrderItem, you will be forced to map this information elsewhere, in a different entity and usually resulting in a different table; this is the Join table that are referred to previously.
  • Unidirectional relationships are sufficient for most uses. If the Order is responsible for accessing OrderItem instances, then you do not need bidirectional relationships. But if you find yourself needing to access the Order for an OrderItem, then you will need a bidirectional relationship. I would suggest reading the Mutual Registration Pattern, so that you will always be able to maintain referential integrity irrespective of any mutation operations performed on Order or OrderItem classes in such a case. Without that pattern, you are almost always going to find yourself seeing vague, unexplained and incorrect object graphs resulting in an inconsistent database state.

If you are not using ORM or you don't intend to, then it would depend on you are accessing the OrderItem instances; in short, it depends on how you are writing your persistence layer. If you are using the DAO pattern, then adding a new method retrieveItemsByOrderId into your DAO interface would be the solution.

Upvotes: 2

Related Questions