JPA Hibernate отношения один-к-одному - PullRequest
62 голосов
/ 25 апреля 2009

У меня отношение один-к-одному, но 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 является собственной стороной, поэтому person использует 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?

Ответы [ 7 ]

85 голосов
/ 25 апреля 2009

JPA не допускает аннотацию @ Id для OneToOne или ManyToOne . То, что вы пытаетесь сделать, - это сопоставление сущностей один-к-одному с общим первичным ключом . Простейший случай - однонаправленный один-к-одному с общим ключом:

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

    @OneToOne
    @PrimaryKeyJoinColumn
    private OtherInfo otherInfo;

    rest of attributes ...
}

Основная проблема заключается в том, что JPA не поддерживает генерацию общего первичного ключа в OtherInfo сущности. Классическая книга Сохранение Java с Hibernate от Бауэра и Кинга дает следующее решение проблемы с использованием расширения 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 ...
}

Также см. здесь .

23 голосов
/ 27 августа 2012

Это также должно работать с использованием аннотации JPA 2.0 @MapsId вместо GenericGenerator 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 ...
}

Подробнее об этом в документации по Hibernate 4.1 в разделе 5.1.2.2.7.

10 голосов
/ 10 октября 2012

Вам просто нужно добавить @JoinColumn(name="column_name") в отношение Host Entity. column_name - это имя столбца базы данных в персональной таблице.

@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 - это имя переменной для otherInfo в классе Person.

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

    rest of attributes ...
}
4 голосов
/ 25 апреля 2009

Я думаю, вам все еще нужно свойство первичного ключа в классе OtherInfo.

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

    @OneToOne(mappedBy="otherInfo")
    public Person person;

    rest of attributes ...
}

Также вам может понадобиться добавить аннотацию @PrimaryKeyJoinColumn на другую сторону сопоставления. Я знаю, что Hibernate использует это по умолчанию. Но тогда я не использовал аннотации JPA, которые, кажется, требуют, чтобы вы указали, как работает ассоциация.

2 голосов
/ 19 мая 2011

У меня есть лучший способ сделать это:

@Entity
public class Person {

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

}

Вот и все

1 голос
/ 25 апреля 2009

Попробуйте это

@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 ...
}
1 голос
/ 25 апреля 2009

Я не уверен, что вы можете использовать отношения как Id / PrimaryKey в Hibernate.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...