J'ai une relation un à un, mais hibernatetool se plaint lors de la génération du schéma. Voici un exemple qui montre le problème:
@Entity
public class Person {
@Id
public int id;
@OneToOne
public OtherInfo otherInfo;
rest of attributes ...
}
La personne a une relation individuelle avec OtherInfo:
@Entity
public class OtherInfo {
@Id
@OneToOne(mappedBy="otherInfo")
public Person person;
rest of attributes ...
}
La personne possède le côté OtherInfo. OtherInfo est le côté possédé, donc personne utilise mappedBy
pour spécifier le nom d'attribut "otherInfo" dans Person.
J'obtiens l'erreur suivante lorsque j'utilise hibernatetool pour générer le schéma de base de données:
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)
...
Une idée pourquoi? Suis-je en train de faire quelque chose de mal ou est-ce un bug Hibernate?
JPA n'autorise pas l'annotation @ Id sur un mappage OneToOne ou ManyToOne. Ce que vous essayez de faire est une association d'entité un-à-un avec une clé primaire partagée . Le cas le plus simple est un à un unidirectionnel avec une clé partagée:
@Entity
public class Person {
@Id
private int id;
@OneToOne
@PrimaryKeyJoinColumn
private OtherInfo otherInfo;
rest of attributes ...
}
Le principal problème avec cela est que JPA ne prend pas en charge la génération de clé primaire partagée dans l'entité OtherInfo. Le livre classique Java Persistence with Hibernate by Bauer and King donne la solution suivante au problème d'utilisation de l'extension 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 ...
}
Voir aussi ici .
Cela devrait également fonctionner en utilisant l'annotation JPA 2.0 @MapsId au lieu du GenericGenerator d'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 ...
}
Plus de détails à ce sujet dans la documentation Hibernate 4.1 sous la section 5.1.2.2.7.
Il vous suffit d'ajouter @JoinColumn(name="column_name")
à la relation Entité hôte. nom_colonne est le nom de la colonne de base de données dans la table personne.
@Entity
public class Person {
@Id
public int id;
@OneToOne
@JoinColumn(name="other_info")
public OtherInfo otherInfo;
rest of attributes ...
}
Personne a une relation un à un avec OtherInfo: mappedBy = "nom_vari" nom_vari est le nom de variable pour otherInfo dans la classe Personne.
@Entity
public class OtherInfo {
@Id
@OneToOne(mappedBy="otherInfo")
public Person person;
rest of attributes ...
}
Je pense que vous avez toujours besoin de la propriété de clé primaire dans la classe OtherInfo.
@Entity
public class OtherInfo {
@Id
public int id;
@OneToOne(mappedBy="otherInfo")
public Person person;
rest of attributes ...
}
En outre, vous devrez peut-être ajouter l'annotation @PrimaryKeyJoinColumn de l'autre côté du mappage. Je sais qu'Hibernate l'utilise par défaut. Mais je n'ai pas utilisé d'annotations JPA, ce qui semble vous obliger à spécifier comment fonctionne l'association.
J'ai une meilleure façon de procéder:
@Entity
public class Person {
@OneToOne(cascade={javax.persistence.CascadeType.ALL})
@JoinColumn(name = "`Id_OtherInfo`")
public OtherInfo getOtherInfo() {
return otherInfo;
}
}
C'est tout
Je ne suis pas sûr que vous puissiez utiliser une relation comme identifiant/clé primaire dans Hibernate.
Essaye ça
@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 ...
}