[Java] En una asociación bidireccional JPA OneToMany / ManyToOne, ¿qué se entiende por "el lado inverso de la asociación"?


Answers

Increíblemente, en 3 años nadie ha respondido a su excelente pregunta con ejemplos de ambas maneras de mapear la relación.

Como lo mencionaron otros, el lado "propietario" contiene el puntero (clave externa) en la base de datos. Puede designar a cualquiera de los lados como propietario, sin embargo, si designa el lado Uno como propietario, la relación no será bidireccional (el lado inverso "muchos" no tendrá conocimiento de su "propietario"). Esto puede ser deseable para la encapsulación / acoplamiento flexible:

// "One" Customer owns the associated orders by storing them in a customer_orders join table
public class Customer {
    @OneToMany(cascade = CascadeType.ALL)
    private List<Order> orders;
}

// if the Customer owns the orders using the customer_orders table,
// Order has no knowledge of its Customer
public class Order {
    // @ManyToOne annotation has no "mappedBy" attribute to link bidirectionally
}

La única solución de mapeo bidireccional es que el lado "muchos" tenga su puntero al "uno", y use el atributo @OneToMany "mappedBy". Sin el atributo "mappedBy", Hibernate esperará una asignación doble (la base de datos tendría tanto la columna de unión como la tabla de unión, que es redundante (por lo general no deseable)).

// "One" Customer as the inverse side of the relationship
public class Customer {
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "customer")
    private List<Order> orders;
}

// "many" orders each own their pointer to a Customer
public class Order {
    @ManyToOne
    private Customer customer;
}
Question

En estos ejemplos en TopLink JPA Annotation Reference :

Ejemplo 1-59 @OneToMany - Clase de cliente con genéricos

@Entity
public class Customer implements Serializable {
    ...
    @OneToMany(cascade=ALL, mappedBy="customer")
    public Set<Order> getOrders() { 
        return orders; 
    }
    ...
}

Ejemplo 1-60 @ManyToOne - Ordenar clase con genéricos

@Entity
public class Order implements Serializable {
    ...
    @ManyToOne
    @JoinColumn(name="CUST_ID", nullable=false)
    public Customer getCustomer() { 
        return customer; 
    }
    ...
}

Me parece que la entidad Customer es el propietario de la asociación. Sin embargo, en la explicación del atributo mappedBy en el mismo documento, está escrito que:

si la relación es bidireccional, establezca el elemento mappedBy en el lado inverso (no propietario) de la asociación con el nombre del campo o propiedad que posee la relación como se muestra en el Ejemplo 1-60.

Sin embargo, si no me equivoco, parece que en el ejemplo, el mappedBy está realmente especificado en el lado propietario de la asociación, en lugar del lado no propietario.

Entonces mi pregunta es básicamente:

  1. En una asociación bidireccional (de uno a muchos / muchos a uno), ¿cuál de las entidades es el propietario? ¿Cómo podemos designar a One Side como propietario? ¿Cómo podemos designar al lado de Muchos como el dueño?

  2. ¿Qué se entiende por "el lado inverso de la asociación"? ¿Cómo podemos designar el lado uno como el inverso? ¿Cómo podemos designar al lado de Muchos como el inverso?




Reglas simples de relaciones bidireccionales:

1. Para las relaciones bidireccionales de muchos a uno, los muchos lados siempre son el lado dueño de la relación. Ejemplo: 1 habitación tiene muchas personas (una persona pertenece solo a una habitación) -> propietario es una persona

2. Para relaciones bidireccionales uno a uno, el lado propietario corresponde al lado que contiene la clave externa correspondiente.

3. Para muchas relaciones bidireccionales, cualquiera de las partes puede ser el lado propietario.

Hope puede ayudarte.




Links