relaciones onetomany one many ejemplo java hibernate jpa

java - onetomany - one to many jpa



RelaciĆ³n JPA Hibernate uno a uno (7)

Tengo una relación uno a uno pero hibernatetool se queja cuando genera el esquema. Aquí hay un ejemplo que muestra el problema:

@Entity public class Person { @Id public int id; @OneToOne public OtherInfo otherInfo; rest of attributes ... }

La persona tiene una relación uno-a-uno con OtherInfo:

@Entity public class OtherInfo { @Id @OneToOne(mappedBy="otherInfo") public Person person; rest of attributes ... }

La persona es dueña del lado de OtherInfo. OtherInfo es el lado de propiedad así que la persona usa mappedBy para especificar el nombre de atributo "otherInfo" en Person.

Recibo el siguiente error cuando uso hibernatetool para generar el esquema de la base de datos:

org.hibernate.MappingException: Could not determine type for: Person, at table: OtherInfo, for columns: [org.hibernate.mapping.Column(person)] at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:292) at org.hibernate.mapping.SimpleValue.createIdentifierGenerator(SimpleValue.java:175) at org.hibernate.cfg.Configuration.iterateGenerators(Configuration.java:743) at org.hibernate.cfg.Configuration.generateDropSchemaScript(Configuration.java:854) at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.java:128) ...

¿Alguna idea de por qué? ¿Estoy haciendo algo mal o es un error de Hibernate?


Creo que todavía necesita la propiedad de clave principal en la clase OtherInfo.

@Entity public class OtherInfo { @Id public int id; @OneToOne(mappedBy="otherInfo") public Person person; rest of attributes ... }

Además, es posible que deba agregar la anotación @PrimaryKeyJoinColumn al otro lado de la asignación. Sé que Hibernate usa esto por defecto. Pero luego no he usado las anotaciones JPA, que parecen requerir que especifiques cómo funciona la asociación.


Esto también debería funcionar con la anotación JPA 2.0 @MapsId en lugar de GenericGenerator de Hibernate:

@Entity public class Person { @Id @GeneratedValue public int id; @OneToOne @PrimaryKeyJoinColumn public OtherInfo otherInfo; rest of attributes ... } @Entity public class OtherInfo { @Id public int id; @MapsId @OneToOne @JoinColumn(name="id") public Person person; rest of attributes ... }

Más detalles sobre esto en la documentación de Hibernate 4.1 en la sección 5.1.2.2.7.


JPA no permite la anotación @Id en una asignación de OneToOne o ManyToOne . Lo que intenta hacer es una asociación de entidad uno a uno con clave primaria compartida . El caso más simple es unidireccional uno a uno con clave compartida:

@Entity public class Person { @Id private int id; @OneToOne @PrimaryKeyJoinColumn private OtherInfo otherInfo; rest of attributes ... }

El principal problema con esto es que JPA no brinda soporte para la generación de claves primarias compartidas en la entidad OtherInfo . El libro clásico Java Persistence con Hibernate de Bauer and King da la siguiente solución al problema usando la extensión Hibernate:

@Entity public class OtherInfo { @Id @GeneratedValue(generator = "customForeignGenerator") @org.hibernate.annotations.GenericGenerator( name = "customForeignGenerator", strategy = "foreign", parameters = @Parameter(name = "property", value = "person") ) private Long id; @OneToOne(mappedBy="otherInfo") @PrimaryKeyJoinColumn public Person person; rest of attributes ... }

Además, mira here .


No estoy seguro de que pueda usar una relación como Id / PrimaryKey en Hibernate.


Prueba esto

@Entity @Table(name="tblperson") public class Person { public int id; public OtherInfo otherInfo; @Id //Here Id is autogenerated @Column(name="id") @GeneratedValue(strategy=GenerationType.AUTO) public int getId() { return id; } public void setId(int id) { this.id = id; } @OneToOne(cascade = CascadeType.ALL,targetEntity=OtherInfo.class) @JoinColumn(name="otherInfo_id") //there should be a column otherInfo_id in Person public OtherInfo getOtherInfo() { return otherInfo; } public void setOtherInfo(OtherInfo otherInfo) { this.otherInfo= otherInfo; } rest of attributes ... } @Entity @Table(name="tblotherInfo") public class OtherInfo { private int id; private Person person; @Id @Column(name="id") @GeneratedValue(strategy=GenerationType.AUTO) public Long getId() { return id; } public void setId(Long id) { this.id = id; } @OneToOne(mappedBy="OtherInfo",targetEntity=Person.class) public College getPerson() { return person; } public void setPerson(Person person) { this.person = person; } rest of attributes ... }


Solo necesita agregar @JoinColumn(name="column_name") a la relación Host Entity. column_name es el nombre de la columna de la base de datos en la tabla de personas.

@Entity public class Person { @Id public int id; @OneToOne @JoinColumn(name="other_info") public OtherInfo otherInfo; rest of attributes ... }

La persona tiene una relación de uno a uno con OtherInfo: mappedBy = "var_name" var_name es el nombre de la variable para otherInfo en la clase Person.

@Entity public class OtherInfo { @Id @OneToOne(mappedBy="otherInfo") public Person person; rest of attributes ... }


Tengo una mejor manera de hacer esto:

@Entity public class Person { @OneToOne(cascade={javax.persistence.CascadeType.ALL}) @JoinColumn(name = "`Id_OtherInfo`") public OtherInfo getOtherInfo() { return otherInfo; } }

Eso es todo