Связь JPA Hibernate "один-к-одному"
У меня есть взаимно-однозначное отношение, но hibernatetool жалуется при создании схемы. Вот пример, который показывает проблему:
@Entity
public class Person {
@Id
public int id;
@OneToOne
public OtherInfo otherInfo;
rest of attributes ...
}
У человека есть взаимно-однозначные отношения с OtherInfo:
@Entity
public class OtherInfo {
@Id
@OneToOne(mappedBy="otherInfo")
public Person person;
rest of attributes ...
}
Лицо принадлежит стороне OtherInfo. OtherInfo - это собственная сторона, поэтому человек использует mappedBy
для указания имени атрибута "otherInfo" в Person.
Я получаю следующую ошибку при использовании hibernatetool для создания схемы базы данных:
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)
...
Любая идея, почему? Я что-то делаю неправильно или это ошибка Hibernate?
Ответы
Ответ 1
JPA не разрешает аннотацию @Id для отображения OneToOne или ManyToOne. То, что вы пытаетесь сделать, - это взаимно однозначная ассоциация сущностей с общим первичным ключом. Самый простой случай - однонаправленный однонаправленный с общим ключом:
@Entity
public class Person {
@Id
private int id;
@OneToOne
@PrimaryKeyJoinColumn
private OtherInfo otherInfo;
rest of attributes ...
}
Основная проблема заключается в том, что JPA не поддерживает поддержку генерации общего первичного ключа в объекте InfoInfo. Классическая книга Сохранение Java с Hibernate by Bauer и King дает следующее решение проблемы с использованием расширения 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 ...
}
Также см. здесь.
Ответ 2
Это должно работать также с помощью JPA 2.0 @MapsId аннотации вместо Hibernate 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 ...
}
Подробнее об этом см. в документации Hibernate 4.1 в разделе 5.1.2.2.7.
Ответ 3
Вам просто нужно добавить отношение @JoinColumn(name="column_name")
к объекту Host Entity. column_name - имя столбца базы данных в таблице person.
@Entity
public class Person {
@Id
public int id;
@OneToOne
@JoinColumn(name="other_info")
public OtherInfo otherInfo;
rest of attributes ...
}
У человека есть взаимно-однозначные отношения с OtherInfo:
mappedBy = "var_name" var_name - это имя переменной для другого объекта в классе Person.
@Entity
public class OtherInfo {
@Id
@OneToOne(mappedBy="otherInfo")
public Person person;
rest of attributes ...
}
Ответ 4
Я думаю, что вам все еще нужно свойство первичного ключа в классе OtherInfo.
@Entity
public class OtherInfo {
@Id
public int id;
@OneToOne(mappedBy="otherInfo")
public Person person;
rest of attributes ...
}
Кроме того, вам может потребоваться добавить аннотацию @PrimaryKeyJoinColumn на другую сторону отображения. Я знаю, что Hibernate использует это по умолчанию. Но тогда я не использовал аннотации JPA, которые, как вам кажется, требуют указать, как ассоциация wokrs.
Ответ 5
У меня есть лучший способ сделать это:
@Entity
public class Person {
@OneToOne(cascade={javax.persistence.CascadeType.ALL})
@JoinColumn(name = "`Id_OtherInfo`")
public OtherInfo getOtherInfo() {
return otherInfo;
}
}
Что все
Ответ 6
Я не уверен, что вы можете использовать отношения как Id/PrimaryKey в спящем режиме.
Ответ 7
Попробуйте это
@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 ...
}