Necesita un ejemplo de una asignación de @OneToOne de clave primaria en Hibernate
-
10-07-2019 - |
Pregunta
¿Puede alguien darme un ejemplo de un mapeo de clave primaria @OneToOne unidireccional en Hibernate? He probado numerosas combinaciones, y hasta ahora lo mejor que he conseguido es esto:
@Entity
@Table(name = "paper_cheque_stop_metadata")
@org.hibernate.annotations.Entity(mutable = false)
public class PaperChequeStopMetadata implements Serializable, SecurityEventAware {
private static final long serialVersionUID = 1L;
@Id
@JoinColumn(name = "paper_cheque_id")
@OneToOne(cascade = {}, fetch = FetchType.EAGER, optional = false, targetEntity = PaperCheque.class)
private PaperCheque paperCheque;
}
Cada vez que Hibernate intenta generar automáticamente el esquema para la asignación anterior, intenta crear la clave primaria como un blob, en lugar de un largo, que es el tipo de identificación de PaperCheque. ¿Alguien puede ayudarme? Si no puedo obtener una solución exacta, algo cercano funcionaría, pero agradecería cualquier respuesta.
Solución
¿Su intención es tener una relación 1-1 entre PaperChequeStopMetaData y PaperCheque? Si es así, no puede definir la instancia de PaperCheque como el @Id de PaperChequeStopMetaData, debe definir una columna @Id separada en PaperChequeStopMetaData.
Otros consejos
Guardé esta discusión cuando implementé un par de asignaciones @OneToOne , Espero que también pueda serle útil, pero no dejamos que Hibernate cree la base de datos para nosotros.
Tenga en cuenta la anotación GenericGenerator.
De todos modos, tengo este código funcionando:
@Entity
@Table(name = "message")
public class Message implements java.io.Serializable
{
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "message_id")
public MessageContent getMessageContent()
{
return messageContent;
}
}
@Entity
@Table(name = "message_content")
@GenericGenerator(name = "MessageContent", strategy = "foreign",
parameters =
{
@org.hibernate.annotations.Parameter
(
name = "property", value = "message"
)
}
)
public class MessageContent implements java.io.Serializable
{
@Id
@Column(name = "message_id", unique = true, nullable = false)
// See http://forum.hibernate.org/viewtopic.php?p=2381079
@GeneratedValue(generator = "MessageContent")
public Integer getMessageId()
{
return this.messageId;
}
}
Gracias a ambos por sus respuestas. Seguí experimentando, y esto es lo que conseguí trabajando:
@Entity
@Table(name = "paper_cheque_stop_metadata")
@org.hibernate.annotations.Entity(mutable = false)
public class PaperChequeStopMetadata implements Serializable, SecurityEventAware {
private static final long serialVersionUID = 1L;
@SuppressWarnings("unused")
@Id
@Column(name = "paper_cheque_id")
@AccessType("property")
private long id;
@OneToOne(cascade = {}, fetch = FetchType.EAGER, optional = false, targetEntity = PaperCheque.class)
@PrimaryKeyJoinColumn(name = "paper_cheque_id")
@JoinColumn(name = "paper_cheque_id", insertable = true)
@NotNull
private PaperCheque paperCheque;
@XmlAttribute(namespace = XMLNS, name = "paper-cheque-id", required = true)
public final long getId() {
return this.paperCheque.getId();
}
public final void setId(long id) {
//this.id = id;
//NOOP, this is essentially a pseudo-property
}
}
Esto es, por supuesto, un truco desagradable, pero me da todo lo que quería. Los accesos de propiedad paperCheque son normales (no se muestran). Me he encontrado con este tipo de problema de mapeo unidireccional OneToOne antes y me decidí por soluciones mucho peores, pero esta vez decidí que iba a resolver, así que seguí hackeando. Una vez más, gracias a ambos por sus respuestas, es muy apreciado.
Simplemente actualizo esta pregunta para futuras vistas.
Cuando se hizo esta pregunta, creo que no había una solución adecuada para este problema. Pero desde JPA 2.0 puede usar @MapsId para resolver este problema.
Referencia con la explicación adecuada: https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/
Debe mantenerse alejado del mapeo OneToOne de hibernate, es muy peligroso. ver http://opensource.atlassian.com/projects/hibernate/browse/HHH -2128
es mejor usar las asignaciones ManyToOne.