2017-04-04 7 views
2

JPAとHibernateアノテーションを使ってデータベースにテーブルを生成することにはいくつかの問題があります。Hibernate/JPAサブクラスからのデータベーステーブルの間違った生成を修正する方法

以下のコードを実行すると、次のEER図で表が生成されます。

Generated EER Diagram of Person, Student and Teacher

これは、私はそれがテーブルを生成する方法ではありません。 まず、テーブル間の関係が間違っている、OneToManyではなくOneToOneである必要があります。 第二に、電子メールが学生と教師の主なキーになることは望ましくありません。

ovNumberが主キーである必要があり、教師employeeNumberが に私は @Idアノテーションでそれをやって試してみましたが、それは私に次のエラーを与える学生に

org.hibernate.mapping.JoinedSubclass cannot be cast to org.hibernate.mapping.RootClass

私は@MappedSuperClassにテーブルを使用しようとすると人は@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)を使用しても生成されません。

は今、私の質問、

は、どのように私は、サブクラス内の別の変数の外部キーとしてスーパークラスのプライマリキーを保ちながらcorrospondingテーブルの主キーを作るのですか?

テーブル間の関係をOneToManyリレーションではなくOneToOneリレーションに修正する方法を教えてください。

これは、どのようにするべきかについてのEER図です。

EER Diagram of Person, Student and Teacher the way it should be

は以下の表を生成するために使用されているモデルクラスです。

Person.java

@Entity 
@Polymorphism(type=PolymorphismType.IMPLICIT) 
@Inheritance(strategy=InheritanceType.JOINED) 
public class Person implements Comparable<Person>, Serializable { 

private static final long serialVersionUID = 1L; 

@Id 
@Column(name="email", length=64, nullable=false) 
private String email; 

@Column(name="firstName", length=255) 
private String firstName; 

@Column(name="insertion", length=255) 
private String insertion; 

@Column(name="lastName", length=255) 
private String lastName; 

public Person() {} 

/** 
* constructor with only email. 
* 
* @param email 
*/ 
public Person(String email) { 
    this.email = email; 
} 

/** 
* @param email 
* @param firstName 
* @param insertion 
* @param lastName 
*/ 
public Person(String email, String firstName, String insertion, String lastName){ 
    this.setEmail(email); 
    this.setFirstName(firstName); 
    this.setInsertion(insertion); 
    this.setLastName(lastName); 
} 

//getters and setters 
public String getEmail() { 
    return email; 
} 

public void setEmail(String email) { 
    this.email = email; 
} 

public String getFirstName() { 
    return firstName; 
} 

public void setFirstName(String firstName) { 
    this.firstName = firstName; 
} 

public String getInsertion() { 
    return insertion; 
} 

public void setInsertion(String insertion) { 
    this.insertion = insertion; 
} 

public String getLastName() { 
    return lastName; 
} 

public void setLastName(String lastName) { 
    this.lastName = lastName; 
} 

@Override 
public int compareTo(Person o) { 
    return email.compareTo(o.getEmail()); 
} 
} 

Teacher.java

@Entity 
@Table(name="teacher") 
@PrimaryKeyJoinColumn(name="email", referencedColumnName="email") 
public class Teacher extends Person { 

private static final long serialVersionUID = 1L; 

//this needs to be the pk of teacher table 
//@Id 
@Column(name="employeeNumber", length=6, nullable=false) 
private int employeeNumber; 

@Column(name="abbreviation", length=6) 
private String abbreviation; 

public Teacher(){} 

/** 
* @param employeeNumber 
* @param email 
* @param firstName 
* @param insertion 
* @param lastName 
*/ 
public Teacher(int employeeNumber, String email, String firstName, String insertion, String lastName){ 
    super(email, firstName, insertion, lastName); 
    this.employeeNumber = employeeNumber; 
    setAbbreviation(); 
} 

public String getAbbreviation() { 
    return abbreviation; 
} 

public void setAbbreviation() { 
    this.abbreviation = getLastName().substring(0, 4).toUpperCase() + getFirstName().substring(0, 2).toUpperCase(); 
} 

public void setAbbreviation(String abbreviation){ 
    this.abbreviation = abbreviation; 
} 

public int getEmployeeNumber() { 
    return employeeNumber; 
} 

public void setEmployeeNumber(int employeeNumber) { 
    this.employeeNumber = employeeNumber; 
} 

@Override 
public String toString() { 
    return "Teacher [abbreviation=" + abbreviation + ", employeeNumber=" + employeeNumber + "]"; 
} 
} 

Student.java

@Entity 
@Table(name="student") 
@PrimaryKeyJoinColumn(name="email", referencedColumnName="email") 
public class Student extends Person { 

private static final long serialVersionUID = 1L; 

@Column(name="cohort") 
private int cohort; 

//FIXME this needs to be the pk of student table 
//@Id 
@Column(name="ovNumber", nullable=false) 
private int studentOV; 


public Student(){} 

public Student(int studentOV, int cohort, String email, String firstName, 
     String insertion, String lastName) { 
    super(email, firstName, insertion, lastName); 
    this.studentOV = studentOV; 
    this.cohort = cohort; 
} 

public int getCohort() { 
    return cohort; 
} 

public void setCohort(int cohort) { 
    this.cohort = cohort; 
} 

public int getStudentOV() { 
    return studentOV; 
} 

public void setStudentOV(int studentOV) { 
    this.studentOV = studentOV; 
} 

@Override 
public int compareTo(Person o) { 
    return getEmail().compareTo(o.getEmail()); 
} 

@Override 
public String toString() { 
    return "Student [firstName=" + getFirstName() + ", insertion=" + getInsertion() + ", lastName=" + getLastName() + ", email=" 
      + getEmail() + ", cohort=" + getCohort() + ", studentOV=" + getStudentOV() + "]"; 
} 
} 

答えて

0

でこれを試してみてください教師と生徒

@OneToOne 
@PrimaryKeyJoinColumn(name="person_email", referencedColumnName="email") 
private Person preson; 

の代わり:

@PrimaryKeyJoinColumn(name="email", referencedColumnName="email") 
+1

これが動作するようには思えない、私は、これはそれを行う方法を知っていますPersonクラス。 TeacherクラスとStudentクラスの両方がPersonクラスを拡張しています。 –

3

あなたの目標は、Personがあなたのスーパークラスである継承を実装することです。 TeacherおよびStudentはそのサブクラスです。 JPAの継承は、SQLの実装と似ていません。私は助言を読むためにfollowing answer私はしばらく前に書いた。また、JavaEE 7 - Entity Inheritance Tutorialも読んでください。

【EDIT】

ここでuはまだ私はそれが奇抜なデザイン(他人のためにオリジナルのメッセージを参照してください)と思い、尋ねた何のために各エンティティの異なる主キーを持つソリューションです:

パーソン:

@Entity 
public class Person implements Serializable { 
    @Id 
    @Column 
    private String email; 

    @OneToOne(mappedBy = "person") 
    private Teacher teacher; 

    @OneToOne(mappedBy = "person") 
    private Student student; 
    //more fields 
} 

教師

@Entity 
public class Teacher implements Serializable { 
    @Id 
    @Column 
    private Integer employeeNumber; 

    //constrained to have to be assigned to a Person 
    //remove constraints if not needed 
    @OneToOne(optional = false) 
    @JoinColumn(unique = true, nullable = false) 
    private Person person; 

    //more fields 
} 
0あなたの問題のために

学生

@Entity 
public class Student implements Serializable { 
    @Id 
    @Column 
    private Integer ovNumber; 

    //constrained to have to be assigned to a Person 
    //remove constraints if not needed 
    @OneToOne(optional = false) 
    @JoinColumn(unique = true, nullable = false) 
    private Person person; 

    //more fields 
} 

【オリジナルメッセージ##

私はあなたのJPA-エンティティを改造することをお勧めします。 Personを抽象エンティティとして宣言し、TeacherとStudentをPerson単位で拡張します。

examplecode:あなたは伸びていない場合

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
@DiscriminatorColumn(name = "PERSON_TYPE") 
public abstract class Person implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column 
    private Integer id; 

    //add your needed fields 
} 

教師と生徒それぞれ

@Entity 
public class Teacher extends Person { 
    //no ID needed, it inherits the id of Person 
} 
+0

あなたの答えをありがとう、これは私が欲しい正しいことをしていないようです。テーブル間の関係は、OneToOneの代わりにOneToManyです。また、電子メールはこの場合常にユニークな値であるため、idを使用しないようにしたい。これはまた、学生と教師のために異なる主キーを設定する部分をカバーしていません。あなたの答えを編集してこれらの問題を解決できるかどうか、感謝します。 –

+0

これは、SQL実装では、OneToMany(1人は複数の生徒になることができます)のようですが、JPAプロバイダは継承を知っているため、それらを一意に扱います。オブジェクトとの関係では、人を保存することはありませんが、教師や生徒は保存しません。別の主キーを持つために、あなたのニーズに合った答えを更新しましたが、あなたのモデルはどういうわけか紛らわしいものです。それにもかかわらず、私は別のPKを使用することによって何の利益も見ません。 –

+0

お時間をいただきありがとうございます。私は、私の必要なポイントの組み合わせが不可能であったという結論に達しました。私は別の主キーをあきらめて、データベースを正しく生成します。しかし、これは私の問題を部分的に解決するあなたの答えをupvote私の問題を正確に解決しません。 –

関連する問題