primarykeyjoincolumn onetoone one many foreign example java jpa one-to-one

java - many - onetoone jpa



JPA @OneToOne con identificación compartida: ¿puedo hacerlo mejor? (2)

Estoy trabajando con un esquema existente que prefiero no cambiar. El esquema tiene una relación uno-a-uno entre las tablas Person y VitalStats, donde Person tiene una clave principal y VitalStats usa el mismo campo que su clave principal y su clave foránea para Person, lo que significa que su valor es el valor de la PK correspondiente. de Persona.

Estos registros son creados por procesos externos, y mi código JPA nunca necesita actualizar VitalStats. Para mi modelo de objeto, me gustaría que mi clase Person contenga un miembro de VitalStats, PERO:

Cuando intento

@Entity public class Person{ private long id; @Id public long getId(){ return id; } private VitalStats vs; @OneToOne(mappedBy = “person”) public VitalStats getVs() { return vs; } } @Entity public class VitalStats{ private Person person; @OneToOne public Person getPerson() { return person; } }

Tengo el problema de que a VitalStats le falta un @Id, que no funciona para un @Entity.

Si intento

@Id @OneToOne public Person getPerson() { return person; }

eso resuelve el problema @Id pero requiere que la persona sea serializable. Volveremos sobre eso.

Podría hacer VitalStats @Embeddable y conectarlo a Person a través de @ElementCollection, pero luego tendría que accederse como una colección, aunque sé que solo hay un elemento. Doable, pero a la vez un poco molesto y un poco confuso.

Entonces, ¿qué me impide decir que la persona implementa Serializable? Nada, en realidad, excepto que me gusta que todo en mi código esté allí por una razón, y no puedo ver ninguna lógica en esto, lo que hace que mi código sea menos legible.

Mientras tanto, simplemente reemplacé el campo Persona en VitalStats con una ID de persona larga e hice esa Id. De VitalStats, por lo que ahora funciona @OneToOne.

Todas estas soluciones a lo que parece (a mí) como un problema directo son un poco torpes, así que me pregunto si me falta algo, o si alguien al menos puede explicarme por qué Persona tiene que ser serializable.

TIA


En mi caso, esto hizo el truco:

Clase de padres:

public class User implements Serializable { private static final long serialVersionUID = 1L; /** auto generated id (primary key) */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(unique = true, nullable = false) private Long id; /** user settings */ @OneToOne(cascade = CascadeType.ALL, mappedBy = "user") private Setting setting; }

Clase de niños:

public class Setting implements Serializable { private static final long serialVersionUID = 1L; /** setting id = user id */ @Id @Column(unique = true, nullable = false) private Long id; /** user with this associated settings */ @MapsId @OneToOne @JoinColumn(name = "id") private User user; }


Para correlacionar la asociación uno a uno utilizando claves primarias compartidas, use la anotación @PrimaryKeyJoinColumn y @MapsId .

Secciones relevantes de la documentación de referencia de Hibernate:

PrimaryKeyJoinColumn

La anotación PrimaryKeyJoinColumn dice que la clave principal de la entidad se usa como el valor de la clave externa para la entidad asociada.

MapsId

La anotación de MapsId le pide a Hibernate que copie el identificador de otra entidad asociada. En la jerga de Hibernate, se lo conoce como generador foráneo, pero el mapeo JPA se lee mejor y se recomienda

Person.java

@Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "person_id") private Long id; @OneToOne(cascade = CascadeType.ALL) @PrimaryKeyJoinColumn private VitalStats vitalStats; }

VitalStats.java

@Entity public class VitalStats { @Id @Column(name="vitalstats_id") Long id; @MapsId @OneToOne(mappedBy = "vitalStats") @JoinColumn(name = "vitalstats_id") //same name as id @Column private Person person; private String stats; }

Tabla de base de

CREATE TABLE person ( person_id bigint(20) NOT NULL auto_increment, name varchar(255) default NULL, PRIMARY KEY (`person_id`) )

Tabla de base de datos VitalStats

CREATE TABLE vitalstats ( vitalstats_id bigint(20) NOT NULL, stats varchar(255) default NULL, PRIMARY KEY (`vitalstats_id`) )