JPA Hibernate Relazione uno-a-uno

Ho una relazione uno-a-uno ma hibernatetool si lamenta quando genera lo schema. Ecco un esempio che mostra il problema:

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

La persona ha una relazione uno-a-uno con OtherInfo:

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

La persona è proprietaria di OtherInfo. OtherInfo è il lato proprietario in cui persona usa mappedBy per specificare il nome dell’attributo “otherInfo” in Person.

Ottengo il seguente errore quando utilizzo hibernatetool per generare lo schema del database:

 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.(SchemaExport.java:128) ... 

Qualche idea del perché? Sto facendo qualcosa di sbagliato o si tratta di un bug Hibernate?

JPA non consente l’annotazione @Id su un mapping OneToOne o ManyToOne . Quello che stai cercando di fare è un’associazione di entity framework one-to-one con chiave primaria condivisa . Il caso più semplice è one-to-one unidirezionale con chiave condivisa:

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

Il problema principale con questo è che JPA non fornisce supporto per la generazione di chiavi primarie condivise nell’ quadro OtherInfo . Il classico libro Java Persistence with Hibernate di Bauer e King offre la seguente soluzione al problema usando l’estensione 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 ... } 

Inoltre, vedi qui .

Questo dovrebbe funzionare anche usando l’annotazione JPA 2.0 @MapsId invece di GenericGenerator di 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 ... } 

Maggiori dettagli su questo nella documentazione di Hibernate 4.1 alla sezione 5.1.2.2.7.

Devi solo aggiungere @JoinColumn(name="column_name") alla relazione Entità host. nome_colonna è il nome della colonna del database nella tabella delle persone.

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

La persona ha una relazione uno-a-uno con OtherInfo: mappedBy = “nome_var” var_name è il nome della variabile per otherInfo nella class Person.

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

Penso che tu abbia ancora bisogno della proprietà della chiave primaria nella class OtherInfo.

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

Inoltre, potrebbe essere necessario aggiungere l’annotazione @PrimaryKeyJoinColumn all’altro lato del mapping. So che Hibernate lo usa di default. Ma poi non ho usato annotazioni JPA, che sembrano richiedere di specificare come i wokrs di associazione.

Ho un modo migliore per farlo:

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

È tutto

Non sono sicuro che tu possa utilizzare una relazione come Id / PrimaryKey in Hibernate.

Prova questo

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