Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Understanding JPA, Part 2: Relationships the JPA way

Handle data relationships with object-oriented grace

  • Print
  • Feedback

Page 3 of 5

Bidirectional one-to-one relationships

Every relationship has two sides:

  • The owning side is responsible for propagating the update of the relationship to the database. Usually this is the side with the foreign key.
  • The inverse side maps to the owning side.

In the one-to-one mapping in the example application, the Invoice object is the owning side. Listing 4 demonstrates what the inverse side -- the Order -- looks like.

Listing 4. An entity in the sample bidirectional one-to-one relationship

@Entity(name = "ORDERS") 
public class Order {
       
       @Id 
       @Column(name = "ORDER_ID", nullable = false)
       @GeneratedValue(strategy = GenerationType.AUTO)
       private long orderId;
       
       @Column(name = "CUST_ID")
       private long custId;
       
       @Column(name = "TOTAL_PRICE", precision = 2)
       private double totPrice;
       
       @Column(name = "OREDER_DESC")
       private String orderDesc;
       
       @Column(name = "ORDER_DATE")  
       private Date orderDt;

       @OneToOne(optional=false,cascade=CascadeType.ALL, 
       mappedBy="order",targetEntity=Invoice.class)
       private Invoice invoice;       
       @Version
       @Column(name = "LAST_UPDATED_TIME")
       private Date updatedTime;

       ....
       //setters and getters goes here
}

Listing 4 maps to the field (order) that owns the relationship by mappedBy="order". targetEntity specifies the owning class name. Another attribute that has been introduced here is cascade. If you are performing insert, update, or delete operations on the Order entity and you want to propagate the same operations to the child object (Invoice, in this case), use the cascade option; you might want to only propagate PERSIST, REFRESH, REMOVE, or MERGE operations, or propagate all of them.

Listing 5 demonstrates how to fetch the invoice details for a particular Order you write.

Listing 5. Fetching objects involved in a bidirectional one-to-one relationship

....
    EntityManager em = entityManagerFactory.createEntityManager();
    Order order = em.find(Order.class, 111);
    System.out.println("Invoice details for order 111 : " + order.getInvoice());
    em.close();
    entityManagerFactory.close();
    ....

Many-to-one relationships

In the previous section, you saw how to successfully retrieve invoice details for a particular order. Now you'll change your focus to see how to get order details for a particular customer, and vice versa. A customer can have zero or more orders, whereas an order is mapped to one customer. Thus, a Customer enjoys a one-to-many relationship with an Order, whereas an Order has a many-to-one relationship with the Customer. This is illustrated in Figure 3.

Diagram of a many-to-one/one-to-many relationship.

Figure 3. A many-to-one/one-to-many relationship (click to enlarge)

Here, the Order entity is the owning side, mapped to Customer by the CUST_ID foreign key. Listing 6 illustrates how a many-to-one relationship can be specified in the Order entity.

Listing 6. A sample entity illustrating a bidirectional many-to-one relationship

@Entity(name = "ORDERS") 
public class Order {
       
       @Id //signifies the primary key
       @Column(name = "ORDER_ID", nullable = false)
       @GeneratedValue(strategy = GenerationType.AUTO)
       private long orderId;
       
       @Column(name = "CUST_ID")
       private long custId;
       
       @OneToOne(optional=false,cascade=CascadeType.ALL, 
       mappedBy="order",targetEntity=Invoice.class)
       private Invoice invoice;

       @ManyToOne(optional=false)
       @JoinColumn(name="CUST_ID",referencedColumnName="CUST_ID")
       private Customer customer;

       ...............
       The other attributes and getters and setters goes here
}


In Listing 6, the Order entity is joined with the Customer entity with the help of the CUST_ID foreign key column. Here also the code specifies optional=false, as each order should have a customer associated to it. The Order entity now has a one-to-one relationship with Invoice and a many-to-one relationship with Customer.

Listing 7 illustrates how to fetch the customer details for a particular Order.

Listing 7. Fetching objects involved in a many-to-one relationship

........
EntityManager em = entityManagerFactory.createEntityManager();
Order order = em.find(Order.class, 111);
System.out.println("Customer details for order 111 : " + order.getCustomer());
em.close();
entityManagerFactory.close();
........

But what happens if you want to find out how many orders have been placed by a customer?

  • Print
  • Feedback

Resources