One-to-many relationships

JPA one-to-many entity relationships can be bidirectional (one entity contains a many-to-one relationship and the corresponding entity contains an inverse one-to-many relationship).

With SQL, one-to-many relationships are defined by foreign keys in one of the tables. The many part of the relationship is the one containing a foreign key to the one part of the relationship. One-to-many relationships defined in an RDBMS are typically unidirectional, since making them bidirectional usually results in denormalized data.

Just like when defining a unidirectional one-to-many relationship in an RDBMS, in JPA the many part of the relationship is the one that has a reference to the one part of the relationship, therefore the annotation used to decorate the appropriate setter method is @ManyToOne.

In the CUSTOMERDB database, there is a unidirectional one-to-many relationship between customers and orders. We define this relationship in the Order entity:

package net.ensode.javaee8book.entityrelationship.entity; 
 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 
 
@Entity 
@Table(name = "ORDERS") 
public class Order 
{ 
  @Id 
  @Column(name = "ORDER_ID") 
  private Long orderId; 
 
  @Column(name = "ORDER_NUMBER") 
  private String orderNumber; 
 
  @Column(name = "ORDER_DESCRIPTION") 
  private String orderDescription; 
 
  @ManyToOne  @JoinColumn(name = "CUSTOMER_ID")  
private Customer customer;
public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public String getOrderDescription() { return orderDescription; } public void setOrderDescription(String orderDescription) { this.orderDescription = orderDescription; } public Long getOrderId() { return orderId; } public void setOrderId(Long orderId) { this.orderId = orderId; } public String getOrderNumber() { return orderNumber; } public void setOrderNumber(String orderNumber) { this.orderNumber = orderNumber; } }

If we were to define a unidirectional many-to-one relationship between the Orders entity and the Customer entity, we wouldn't need to make any changes to the Customer entity. To define a bidirectional one-to-many relationship between the two entities, a new field decorated with the @OneToMany annotation needs to be added to the Customer entity:

package net.ensode.javaee8book.entityrelationship.entity; 
 
import java.io.Serializable; 
import java.util.Set; 
 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.OneToMany; 
import javax.persistence.Table; 
 
@Entity 
@Table(name = "CUSTOMERS") 
public class Customer implements Serializable 
{ 
  @Id 
  @Column(name = "CUSTOMER_ID") 
  private Long customerId; 
 
  @Column(name = "FIRST_NAME") 
  private String firstName; 
 
  @Column(name = "LAST_NAME") 
  private String lastName; 
 
  private String email; 
 
  @OneToOne(mappedBy = "customer") 
  private LoginInfo loginInfo; 
 
  @OneToMany(mappedBy="customer")  
private Set<Order> orders;
public Long getCustomerId() { return customerId; } public void setCustomerId(Long customerId) { this.customerId = customerId; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public LoginInfo getLoginInfo() { return loginInfo; } public void setLoginInfo(LoginInfo loginInfo) { this.loginInfo = loginInfo; } public Set<Order> getOrders()
{
return orders;

}

public void setOrders(Set<Order> orders)

{

this.orders = orders;

}
}

The only difference between this version of the Customer entity and the previous one is the addition of the orders field and related getter and setter methods. Of special interest is the @OneToMany annotation decorating this field. The mappedBy attribute must match the name of the corresponding field in the entity corresponding to the many part of the relationship. In simple terms, the value of the mappedBy attribute must match the name of the field decorated with the @ManyToOne annotation in the bean at the other side of the relationship.

The following example code illustrates how to persist one-to-many relationships to the database:

package net.ensode.javaee8book.entityrelationship.namedbean; 
 
import javax.annotation.Resource; 
import javax.enterprise.context.RequestScoped; 
import javax.inject.Named; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
import javax.transaction.HeuristicMixedException; 
import javax.transaction.HeuristicRollbackException; 
import javax.transaction.NotSupportedException; 
import javax.transaction.RollbackException; 
import javax.transaction.SystemException; 
import javax.transaction.UserTransaction; 
import net.ensode.javaee8book.entityrelationship.entity.Customer; 
import net.ensode.javaee8book.entityrelationship.entity.Order; 
 
@Named 
@RequestScoped 
public class OneToManyRelationshipDemoBean { 
 
    @PersistenceContext 
    private EntityManager entityManager; 
 
    @Resource 
    private UserTransaction userTransaction; 
 
    public String updateDatabase() { 
        String retVal = "confirmation"; 
 
        Customer customer; 
        Order order1; 
        Order order2; 
 
        order1 = new Order(); 
        order1.setOrderId(1L); 
        order1.setOrderNumber("SFX12345"); 
        order1.setOrderDescription("Dummy order."); 
 
        order2 = new Order(); 
        order2.setOrderId(2L); 
        order2.setOrderNumber("SFX23456"); 
        order2.setOrderDescription("Another dummy order."); 
 
        try { 
            userTransaction.begin(); 
 
            customer = entityManager.find(Customer.class, 4L); 
 
            order1.setCustomer(customer); 
            order2.setCustomer(customer); 
 
            entityManager.persist(order1); 
            entityManager.persist(order2); 
 
            userTransaction.commit(); 
 
        } catch (NotSupportedException | 
                SystemException | 
                SecurityException | 
                IllegalStateException | 
                RollbackException | 
                HeuristicMixedException | 
                HeuristicRollbackException e) { 
            retVal = "error"; 
            e.printStackTrace(); 
        } 
 
        return retVal; 
    } 
} 

The preceding code is pretty similar to the previous example. It instantiates two instances of the Order entity, populates them with some data, then in a transaction an instance of the Customer entity is located and used as the parameter of the setCustomer() method of both instances of the Order entity. We then persist both Order entities by invoking EntityManager.persist() for each one of them.

Just like when dealing with one-to-one relationships, what happens behind the scenes is that the CUSTOMER_ID column of the ORDERS table in the CUSTOMERDB database is populated with the primary key corresponding to the related row in the CUSTOMERS table.

Since the relationship is bidirectional, we can obtain all orders related to a customer by invoking the getOrders() method on the Customer entity.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.209.201