unidirectional onetomany one many ejemplo java hibernate jpa orm one-to-many

java - ejemplo - ¿Cuál es la diferencia entre @JoinColumn y mappedBy al usar una asociación JPA @OneToMany?



one-to-many hibernate ejemplo (5)

Como expliqué en este artículo , si usa la anotación @JoinColumn con @JoinColumn , entonces tiene una asociación unidireccional.

Si usa @OneToMany con el mappedBy atributos mappedBy , tiene una asociación bidireccional, lo que significa que necesita tener una asociación @ManyToOne en el lado secundario al que mappedBy referencia mappedBy .

La asociación unidireccional @OneToMany no funciona muy bien , por lo que debe evitarla.

Es mejor utilizar el @OneToMany bidireccional que es más eficiente .

Cuál es la diferencia entre:

@Entity public class Company { @OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY) @JoinColumn(name = "companyIdRef", referencedColumnName = "companyId") private List<Branch> branches; ... }

y

@Entity public class Company { @OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY, mappedBy = "companyIdRef") private List<Branch> branches; ... }


La anotación @JoinColumn indica que esta entidad es la propietaria de la relación (es decir: la tabla correspondiente tiene una columna con una clave externa a la tabla referenciada), mientras que el atributo mappedBy indica que la entidad en este lado es la inversa de relación, y el propietario reside en la "otra" entidad. Esto también significa que puede acceder a la otra tabla desde la clase que ha anotado con "mappedBy" (relación totalmente bidireccional).

En particular, para el código en la pregunta, las anotaciones correctas se verían así:

@Entity public class Company { @OneToMany(fetch = FetchType.LAZY, mappedBy = "company") private List<Branch> branches; } @Entity public class Branch { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "companyId") private Company company; }


La anotación mappedBy idealmente debería usarse siempre en el lado principal (clase de empresa) de la relación bidireccional, en este caso debería estar en la clase de empresa que apunta a la variable miembro ''company'' de la clase secundaria (clase de rama)

La anotación @JoinColumn se usa para especificar una columna asignada para unirse a una asociación de entidad, esta anotación se puede usar en cualquier clase (principal o secundaria), pero lo ideal sería que se use solo en un lado (ya sea en la clase primaria o en la clase secundaria) en ambos) aquí, en este caso, lo usé en el lado Infantil (clase de rama) de la relación bidireccional que indica la clave externa en la clase de rama.

A continuación se muestra el ejemplo de trabajo:

clase padre, empresa

@Entity public class Company { private int companyId; private String companyName; private List<Branch> branches; @Id @GeneratedValue @Column(name="COMPANY_ID") public int getCompanyId() { return companyId; } public void setCompanyId(int companyId) { this.companyId = companyId; } @Column(name="COMPANY_NAME") public String getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,mappedBy="company") public List<Branch> getBranches() { return branches; } public void setBranches(List<Branch> branches) { this.branches = branches; } }

clase infantil, rama

@Entity public class Branch { private int branchId; private String branchName; private Company company; @Id @GeneratedValue @Column(name="BRANCH_ID") public int getBranchId() { return branchId; } public void setBranchId(int branchId) { this.branchId = branchId; } @Column(name="BRANCH_NAME") public String getBranchName() { return branchName; } public void setBranchName(String branchName) { this.branchName = branchName; } @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="COMPANY_ID") public Company getCompany() { return company; } public void setCompany(Company company) { this.company = company; } }


Solo me gustaría agregar que @JoinColumn no siempre tiene que estar relacionado con la ubicación de la información física como sugiere this respuesta. Puede combinar @JoinColumn con @OneToMany incluso si la tabla principal no tiene datos de tabla que apunten a la tabla secundaria.

Cómo definir la relación unidireccional de OneToMany en JPA

OneToMany unidireccional, No Invertir ManyToOne, No Join Table

Aunque parece que solo está disponible en JPA 2.x+ . Es útil para situaciones en las que desea que la clase secundaria solo contenga el ID del padre, no una referencia completa.


@JoinColumn podría usarse en ambos lados de la relación. La pregunta era sobre el uso de @JoinColumn en el lado de @OneToMany (caso raro). Y el punto aquí está en la duplicación de información física (nombre de columna) junto con una consulta SQL no optimizada que producirá algunas declaraciones de ACTUALIZACIÓN adicionales .

Según la documentation :

Dado que muchos a uno son (casi) siempre el lado propietario de una relación bidireccional en la especificación JPA, la asociación de uno a muchos está anotada por @OneToMany (mappedBy = ...)

@Entity public class Troop { @OneToMany(mappedBy="troop") public Set<Soldier> getSoldiers() { ... } @Entity public class Soldier { @ManyToOne @JoinColumn(name="troop_fk") public Troop getTroop() { ... }

La tropa tiene una relación bidireccional de uno a muchos con el soldado a través de la propiedad de la tropa. No tiene que (no debe) definir ninguna asignación física en el lado mappedBy.

Para asignar un bidireccional a muchos, con el lado uno a muchos como el lado propietario , debe eliminar el elemento mappedBy y establecer el valor de muchos en uno @JoinColumn como insertable y actualizable a falso. Esta solución no está optimizada y producirá algunas declaraciones de ACTUALIZACIÓN adicionales.

@Entity public class Troop { @OneToMany @JoinColumn(name="troop_fk") //we need to duplicate the physical information public Set<Soldier> getSoldiers() { ... } @Entity public class Soldier { @ManyToOne @JoinColumn(name="troop_fk", insertable=false, updatable=false) public Troop getTroop() { ... }