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 2 of 5

One-to-one relationships

First off, the example application will need to address the order-invoice relationship. For each order, there will be an invoice; and, similarly, each invoice is associated with an order. These two tables are related with one-to-one mapping as shown in Figure 2, joined with the help of the foreign key ORDER_ID. JPA facilitates one-to-one mapping with the help of the @OneToOne annotation.

Diagram of a one-to-one relationship

Figure 2. A one-to-one relationship (click to enlarge)

The sample application will fetch the order data for a particular invoice ID. The Invoice entity shown in Listing 1 maps all the fields of the INVOICE table as attributes and has an Order object joined with the ORDER_ID foreign key.

Listing 1. A sample entity depicting a one-to-one relationship

@Entity(name = "ORDER_INVOICE") 
public class Invoice {
       
       @Id 
       @Column(name = "INVOICE_ID", nullable = false)
       @GeneratedValue(strategy = GenerationType.AUTO)
       private long invoiceId;
       
       @Column(name = "ORDER_ID")
       private long orderId;
       
       @Column(name = "AMOUNT_DUE", precision = 2)
       private double amountDue;
       
       @Column(name = "DATE_RAISED")  
       private Date orderRaisedDt;

       @Column(name = "DATE_SETTLED")  
       private Date orderSettledDt;
       
       @Column(name = "DATE_CANCELLED")  
       private Date orderCancelledDt;
       
       @Version
       @Column(name = "LAST_UPDATED_TIME")
       private Date updatedTime;
       @OneToOne(optional=false)
       @JoinColumn(name = "ORDER_ID") 
       private Order order;       
       ...
       //getters and setters goes here
}

The @OneToOne and the @JoinCloumn annotations in Listing 1 are internally resolved by the persistence provider, as illustrated in Listing 2.

Listing 2. SQL query resolving a one-to-one relationship

SELECT t0.LAST_UPDATED_TIME, t0.AMOUNT_PAID, t0.ORDER_ID, 
t0.DATE_RAISED ,t1.ORDER_ID, t1.LAST_UPDATED_TIME, t1.CUST_ID,
t1.OREDER_DESC, t1.ORDER_DATE, t1.TOTAL_PRICE 
FROM ORDER_INVOICE t0 
INNER JOIN ORDERS t1 ON t0.ORDER_ID = t1.ORDER_ID 
WHERE t0.INVOICE_ID = ?

The query in Listing 2 shows an inner join between the ORDERS and INVOICE tables. But what happens if you need an outer join relationship? You can control the join type very easily by setting the optional attribute of @OneToOne to either true or false to indicate whether or not the association is optional. The default value is true, which signifies that the related object may or may not exist and that the join will be an outer join in that case. Since each order must have an invoice and vice versa, in this case the optional attribute has been set to false.

Listing 3 demonstrates how to fetch an order for a particular invoice you write.

Listing 3. Fetching objects involved in a one-to-one relationship

....
EntityManager em = entityManagerFactory.createEntityManager();
Invoice invoice = em.find(Invoice.class, 1);
System.out.println("Order for invoice 1 : " + invoice.getOrder());
em.close();
entityManagerFactory.close();
....

But what happens if you want to fetch the invoice for a particular order?

  • Print
  • Feedback

Resources