¿Alguien puede explicarme @MapsId
en hibernación? Me cuesta entenderlo.
Sería genial si uno pudiera explicarlo con un ejemplo y ¿en qué tipo de casos de uso es más aplicable?
¿Alguien puede explicarme @MapsId
en hibernación? Me cuesta entenderlo.
Sería genial si uno pudiera explicarlo con un ejemplo y ¿en qué tipo de casos de uso es más aplicable?
Respuestas:
Aquí hay una buena explicación de Object DB .
Designa un atributo de relación ManyToOne o OneToOne que proporciona la asignación para una clave principal EmbeddedId, un atributo dentro de una clave principal EmbeddedId o una clave principal simple de la entidad principal. El elemento de valor especifica el atributo dentro de una clave compuesta al que corresponde el atributo de relación. Si la clave principal de la entidad es del mismo tipo de Java que la clave principal de la entidad a la que hace referencia la relación, no se especifica el atributo de valor.
// parent entity has simple primary key
@Entity
public class Employee {
@Id long empId;
String name;
...
}
// dependent entity uses EmbeddedId for composite key
@Embeddable
public class DependentId {
String name;
long empid; // corresponds to primary key type of Employee
}
@Entity
public class Dependent {
@EmbeddedId DependentId id;
...
@MapsId("empid") // maps the empid attribute of embedded id
@ManyToOne Employee emp;
}
Lea los documentos de API aquí.
@MapsId
tendrá en la capa de persistencia (base de datos) solo la columna de clave principal. La idea es compartir la clave principal entre las dos entidades.
Dependent
simplemente conociendo el identificador de Employee
.
Encontré esta nota también útil: @MapsId
en la anotación de hibernación mapea una columna con la columna de otra tabla.
También se puede utilizar para compartir la misma clave primaria entre 2 tablas.
Ejemplo:
@Entity
@Table(name = "TRANSACTION_CANCEL")
public class CancelledTransaction {
@Id
private Long id; // the value in this pk will be the same as the
// transaction line from transaction table to which
// this cancelled transaction is related
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ID_TRANSACTION", nullable = false)
@MapsId
private Transaction transaction;
....
}
@Entity
@Table(name = "TRANSACTION")
@SequenceGenerator(name = "SQ_TRAN_ID", sequenceName = "SQ_TRAN_ID")
public class Transaction {
@Id
@GeneratedValue(generator = "SQ_TRAN_ID", strategy = GenerationType.SEQUENCE)
@Column(name = "ID_TRANSACTION", nullable = false)
private Long id;
...
}
@MapsId
. ¿Incluso hace alguna diferencia?
@Id
y @GeneratedValue
y @Column
) y tendrá un @OneToOne
y @JoinColumn
con la otra mesa, y la otra mesa tendrá el @MapsId
. Sin embargo, esto probablemente no funcionaría si primero quisiera INSERTAR en la "otra tabla".
Como explicó Vladimir en su tutorial , la mejor manera de mapear una relación @OneToOne es usar @MapsId. De esta manera, ni siquiera necesita una asociación bidireccional, ya que siempre puede obtener la entidad secundaria utilizando el identificador de la entidad principal.
MapsId le permite usar la misma clave principal entre dos entidades / tablas diferentes. Nota: cuando usa MapsId, la CASCADE.ALL
bandera se vuelve inútil y deberá asegurarse de que sus entidades se guarden manualmente.
En mi humilde opinión, la mejor manera de pensar @MapsId
es cuando necesita mapear una clave compuesta en una entidad: m.
Por ejemplo, un cliente puede tener uno o más consultores y un consultor puede tener uno o más clientes:
Y sus entradas serían algo como esto (pseudo código Java):
@Entity
public class Customer {
@Id
private Integer id;
private String name;
}
@Entity
public class Consultant {
@Id
private Integer id;
private String name;
@OneToMany
private List<CustomerByConsultant> customerByConsultants = new ArrayList<>();
public void add(CustomerByConsultant cbc) {
cbc.setConsultant(this);
this.customerByConsultant.add(cbc);
}
}
@Embeddable
public class ConsultantByConsultantPk implements Serializable {
private Integer customerId;
private Integer consultantId;
}
@Entity
public class ConsultantByConsultant {
@EmbeddedId
private ConsultantByConsultantPk id = new ConsultantByConsultantPk();
@MapsId("customerId")
@JoinColumn(insertable = false, updatable = false)
Customer customer;
@MapsId("consultantId")
@JoinColumn(insertable = false, updatable = false)
Consultant consultant;
}
Al mapear de esta manera, JPA inserta Customer
e Consultant
identifica automáticamente en el EmbeddableId
cada vez que guarda un consultor. Por lo tanto, no es necesario crear manualmente el archivo ConsultantByConsultantPk
.