JPA Hibernate Uno-a-Uno

Tengo un uno-a-uno, pero hibernatetool se queja a la hora de generar el esquema. He aquí un ejemplo que muestra el problema:

@Entity
public class Person {
    @Id
    public int id;

    @OneToOne
    public OtherInfo otherInfo;

    rest of attributes ...
}

Persona tiene un uno-a-uno en relación con OtherInfo:

@Entity
public class OtherInfo {
    @Id
    @OneToOne(mappedBy="otherInfo")
    public Person person;

    rest of attributes ...
}

Persona es propietaria de un lado de OtherInfo. OtherInfo es la propiedad de costado para que la persona utiliza mappedBy para especificar el nombre del atributo «otherInfo» en Persona.

Me sale el siguiente error cuando se utiliza hibernatetool para generar el esquema de 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 esta una de Hibernación error?

InformationsquelleAutor Steve Kuo | 2009-04-24

7 Kommentare

  1. 85

    JPA no permite la @Id anotación en un OneToOne o ManyToOne de asignación. Lo que estamos tratando de hacer es de uno-a-uno de la entidad asociación de compartido clave principal. 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 proporciona soporte para compartir la clave primaria de generación en OtherInfo entidad. El libro clásico de Persistencia Java con Hibernate por Bauer y el Rey da la siguiente solución para el problema usando Hibernate extensión:

    @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 ...
    }

    También, ver aquí.

    • Gran respuesta, sólo quería añadir que usted puede necesitar agregar la siguiente anotación, así como en su clase de Persona (yo tenía que conseguir que las cosas funcionen correctamente): @Cascade({ CascadeType.ALL, CascadeType.DELETE_ORPHAN })
    • Gracias, me ayudó en mi problema.. ¿sabe usted de todos modos el uso de sólo las anotaciones JPA y evitar la hibernación uno?
    • si hay una manera en la que debe estar en JPA 2.0 – no me fijé en esto, sin embargo.
    • Funcionó para mí, pero he tenido que añadir optional=false a la @OneToOne anotación. De lo contrario, me gustaría obtener una excepción se quejaban de que la persona era nula.
  2. 23

    Esto se debe trabajar también con JPA 2.0 @MapsId anotación en lugar de Hibernación de la GenericGenerator:

    @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 modo de Hibernación 4.1 documentación en la sección 5.1.2.2.7.

    • Enlace para los perezosos. Decidí usar el Id de anotación en el OneToOne propia clase (OtherInfo en tu ejemplo), pero que sólo funciona en un niño-padre escenario. Gracias por la respuesta!
    • ¿Por qué especificar @JoinColumn en OtherInfo en lugar de utilizar @PrimaryKeyJoinColumn?
  3. 10

    Sólo se necesita añadir @JoinColumn(name="column_name") Anfitrión de Entidad relación . column_name es la base de datos nombre de la columna en la tabla persona.

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

    Persona tiene un uno-a-uno en relación con OtherInfo:
    mappedBy=»var_nombre» var_nombre es el nombre de la variable para otherInfo en clase de Persona.

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

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

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

    También, usted puede necesitar agregar el @PrimaryKeyJoinColumn anotación al otro lado de la asignación. Sé que Hibernate utiliza esta opción por defecto. Pero entonces no he utilizado las anotaciones JPA, que parecen requerir que usted especifique cómo la asociación wokrs.

  5. 2

    Tengo una mejor forma de hacer esto:

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

    Que todo

    • También la propiedad de lado, es decir, el lado que tiene la clave externa debe implementar serialisable (con hiberate 4 /jpa 2)
  6. 1

    No estoy seguro de que usted puede utilizar una relación como un Id/PrimaryKey en modo de Hibernación.

  7. 1

    Probar este

    @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 ...
    }

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea