2009-04-24 3 views
59

나는 일대일 관계를 가지고 있지만 스키마를 생성 할 때 hibernatetool이 불평한다.JPA Hibernate 일대일 관계

@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을 사용하여 Person의 속성 이름 "otherInfo"를 지정합니다. 왜

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) 
     ... 

어떤 생각 : 데이터베이스 스키마를 생성하는 hibernatetool를 사용하는 경우

나는 다음과 같은 오류가? 제가 잘못했거나 최대 절전 모드 버그입니까?

답변

85

JPA는 OneToOne 또는 ManyToOne 매핑에 @Id 주석을 허용하지 않습니다. 당신이하려고하는 것은 1 : 1 엔티티 연합 과 공유 프라이 머리 키입니다. 가장 간단한 경우는 단방향 일대일 공유 키 :

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

    @OneToOne 
    @PrimaryKeyJoinColumn 
    private OtherInfo otherInfo; 

    rest of attributes ... 
} 

이 주요 문제는 JPA가 OtherInfo 엔티티에서 공유 차 키 생성에 대한 지원을 제공하지 않는다는 점이다.

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

또한, here 참조 : 고전적인 책 Java Persistence with Hibernate by Bauer and King는 최대 절전 모드 확장을 사용하여 문제에 대한 다음과 같은 솔루션을 제공합니다.

+3

멋진 대답은, 당신이 당신의 Person 클래스에서뿐만 아니라 다음과 같은 주석을 추가해야 할 수도 추가 싶어 (I가 제대로 작동 것들을 얻을에 있었다) :'@Cascade ({CascadeType.ALL, CascadeType. DELETE_ORPHAN})' –

+0

고마워, 내 문제에 도움이 .. 어쨌든 JPA 주석 만 사용하고 최대 절전 모드를 피할 수 있습니까? – Elton

+0

@Elton - JPA 2.0에 있어야 할 방법이 있다면 - 나는 이것을 보지 않았다. – topchef

1

최대 절전 모드에서 Id/PrimaryKey 관계를 사용할 수 있는지 확신하지 못합니다.

1

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

나는 여전히 OtherInfo 클래스의 기본 키 속성을 필요가 있다고 생각하십시오.

또한 매핑의 다른쪽에 @PrimaryKeyJoinColumn 주석을 추가해야 할 수도 있습니다. 나는 Hibernate가 기본적으로 이것을 사용한다는 것을 알고있다. 하지만 JPA 주석을 사용하지 않았습니다. JPA 주석을 사용하는 방법에 대한 설명이 필요합니다.

2

나는이 일을 더 나은 방법이 있습니다

@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의 GenericGenerator의 JPA 2.0 @MapsId 주석을 사용하여 작업을해야합니다 모든

+0

소유 된 쪽, 즉 외래 키가있는 쪽이 serializeable (hiberate 4/jpa 2) –

22

@Entity 
public class Person { 

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

} 

5.1.2.2.7 절의 Hibernate 4.1 문서에서 이에 대한 세부 사항.

+1

을 구현해야합니다. [Lazy 링크] (https://docs.jboss.org/hibernate/orm/4.1/manual/ko-US/html_single/# d5e2666). IdTo 주석을 OneToOne 클래스 자체 (예 : OtherInfo)에서 사용하기로 선택했으나 자식 부모 시나리오에서만 작동합니다. 답변 해주셔서 감사합니다! – Joe

+2

'@ PrimaryKeyJoinColumn'을 사용하지 않고 왜 'OtherInfo'에'@ JoinColumn'을 지정 했습니까? –

10

호스트 엔터티 관계에 @JoinColumn(name="column_name")을 추가하기 만하면됩니다. column_name은 person 테이블의 데이터베이스 열 이름입니다. mappedBy = "var_name 반"var_name 반은 Person 클래스의 otherInfo위한 변수 이름 :

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

    @OneToOne 
    @JoinColumn(name="other_info") 
    public OtherInfo otherInfo; 

    rest of attributes ... 
} 

사람 OtherInfo와 일대일 관계를 갖는다.

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

    rest of attributes ... 
}