2020-04-16

Hibernate JPA @OneToMany Example

@OneToMany

The @OneToMany annotation is used to specify a one-to-many database relationship.

OneToMany specifies a many-valued association with one-to-many multiplicity.
If the collection is defined using generics to specify the element type, the associated target entity type need not be specified; otherwise the target entity class must be specified. If the relationship is bidirectional, the mappedBy element must be used to specify the relationship field or property of the entity that is the owner of the relationship.

The OneToMany annotation may be used within an embeddable class contained within an entity class to specify a relationship to a collection of entities. If the relationship is bidirectional, the mappedBy element must be used to specify the relationship field or property of the entity that is the owner of the relationship. When the collection is a java.util.Map, the cascade element and the orphanRemoval element apply to the map value.


    Example 1: One-to-Many association using generics

    // In Customer class:

    @OneToMany(cascade=ALL, mappedBy="customer")
    public Set<Order> getOrders() { return orders; }

    In Order class:

    @ManyToOne
    @JoinColumn(name="CUST_ID", nullable=false)
    public Customer getCustomer() { return customer; }


    Example 2: One-to-Many association without using generics

    // In Customer class:

    @OneToMany(targetEntity=com.acme.Order.class, cascade=ALL,
                mappedBy="customer")
    public Set getOrders() { return orders; }

    // In Order class:

    @ManyToOne
    @JoinColumn(name="CUST_ID", nullable=false)
    public Customer getCustomer() { return customer; }


    Example 3: Unidirectional One-to-Many association using a foreign key mapping

    // In Customer class:

    @OneToMany(orphanRemoval=true)
    @JoinColumn(name="CUST_ID") // join column is in table for Order
    public Set<Order> getOrders() {return orders;}
   

The @OneToMany association links a parent entity with one or more child entities. If the @OneToMany doesn’t have a mirroring @ManyToOne association on the child side, the @OneToMany association is unidirectional. If there is a @ManyToOne association on the child side, the @OneToMany association is bidirectional and the application developer can navigate this relationship from both ends.

Unidirectional @OneToMany

When using a unidirectional @OneToMany association, Hibernate resorts to using a link table between the two joining entities.

Unidirectional @OneToMany association

@Entity(name = "Person")
public static class Person {

@Id
@GeneratedValue
private Long id;

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<Phone> phones = new ArrayList<>();

//Getters and setters are omitted for brevity

}

@Entity(name = "Phone")
public static class Phone {

@Id
@GeneratedValue
private Long id;

@Column(name = "`number`")
private String number;

//Getters and setters are omitted for brevity

}

Cascading @OneToMany association

Person person = new Person();
Phone phone1 = new Phone( "123-456-7890" );
Phone phone2 = new Phone( "321-654-0987" );

person.getPhones().add( phone1 );
person.getPhones().add( phone2 );
entityManager.persist( person );
entityManager.flush();

person.getPhones().remove( phone1 );

Bidirectional @OneToMany

The bidirectional @OneToMany association also requires a @ManyToOne association on the child side. Although the Domain Model exposes two sides to navigate this association, behind the scenes, the relational database has only one foreign key for this relationship.

Every bidirectional association must have one owning side only (the child side), the other one being referred to as the inverse (or the mappedBy) side.

@OneToMany association mappedBy the @ManyToOne side

@Entity(name = "Person")
public static class Person {

@Id
@GeneratedValue
private Long id;

@OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Phone> phones = new ArrayList<>();

//Getters and setters are omitted for brevity

public void addPhone(Phone phone) {
phones.add( phone );
phone.setPerson( this );
}

public void removePhone(Phone phone) {
phones.remove( phone );
phone.setPerson( null );
}
}

@Entity(name = "Phone")
public static class Phone {

@Id
@GeneratedValue
private Long id;

@NaturalId
@Column(name = "`number`", unique = true)
private String number;

@ManyToOne
private Person person;

//Getters and setters are omitted for brevity

@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Phone phone = (Phone) o;
return Objects.equals( number, phone.number );
}

@Override
public int hashCode() {
return Objects.hash( number );
}
}


No comments:

Post a Comment