2017-04-04 1 views
2

Ich habe einige Schwierigkeiten haben, mit Tabellen in der Datenbank durch JPA Erzeugung und Anmerkungen Hibernate.Hibernate/JPA Wie falsch Generierung von Datenbanktabellen von Unterklassen zu beheben

Wenn der Code ausgeführt wird unten Er erzeugt die Tabellen mit den folgenden EER-Diagramm.

Generated EER Diagram of Person, Student and Teacher

Dies ist nicht, wie ich es die Tabellen erstellt werden soll. Zunächst sind die Beziehungen zwischen den Tabellen falsch, sie müssen OneToOne und nicht OneToMany sein. Zweitens möchte ich nicht, dass E-Mail der primäre Schlüssel in Schüler und Lehrer ist.

In Student sollte die ovNumber Primärschlüssel sein und in dem Lehrer der employeeNumber Ich habe es zu tun versucht, mit der @Id Anmerkung, aber das gibt mir die folgende Fehlermeldung:

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

Wenn ich versuche @MappedSuperClass die Tabelle zu verwenden, Person erzeugt nicht, auch wenn Sie @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) verwenden.

Nun meine Frage,

Wie kann ich eine andere Variable in Subklassen der Primärschlüssel für die Tabelle corrosponding während des übergeordneten Klasse Primärschlüssel als Fremdschlüssel zu halten?

Wie behebe ich die Beziehung zwischen den Tabellen eine OneToOne Beziehung zu sein, anstatt eine OneToMany Beziehung? Hier

ist ein EER Diagramm, wie es sein sollte.

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

Im Folgenden sind die Modellklassen, die verwendet werden, um die Tabellen zu erzeugen.

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() + "]"; 
} 
} 

Antwort

0

versuchen, dies in Lehrer und Schüler

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

statt:

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

dies nicht zu funktionieren scheint, ich weiß, dass dies der richtige Weg ist, es zu tun, wenn Sie erstrecken sich nicht die Klasse Person. Die Klassen "Lehrer" und "Schüler" erweitern jedoch die Klasse "Person". –

3

Ihr Ziel ist die Vererbung zu implementieren, wo Person ist der Superklasse. Teacher und Student sind Unterklassen davon. Vererbung in JPA ist nicht wie seine SQL-Implementierung. Ich rate zu lesen following answer Ich schrieb vor einer Weile. Lesen Sie auch JavaEE 7 - Entity Inheritance Tutorial.

## EDIT ##

Hier ist die Lösung mit verschiedenen Primärschlüsseln für jede Einheit für das, was u gefragt, noch denke ich, dass ungewöhnliches Design ist (für andere finden Sie in Original-Nachricht):

Person:

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

Lehrer

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

Studenten

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

## Original Message ##

Für Ihr Problem Ich schlage vor, Ihre JPA-Entitäten neu zu gestalten. Person als abstrakte Entität deklarieren, Lehrer und Schüler nach Person erweitern

examplecode:

Person

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

Lehrer und Schüler jeweils

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

Vielen Dank für Ihre Antwort, das scheint nicht das Richtige zu tun, was ich will. Die Beziehungen zwischen den Tabellen sind immer noch OneToMany anstelle von OneToOne. Auch ich möchte vermeiden, ID als E-Mail zu verwenden, ist in diesem Fall immer ein eindeutiger Wert. Dies deckt auch nicht den Teil der Einstellung verschiedener Primärschlüssel für Schüler und Lehrer ab. Ich würde mich freuen, wenn Sie Ihre Antwort bearbeiten könnten, um diese Probleme zu beheben. –

+0

In seiner SQL-Implementierung scheint es, dass sie OneToMany sind (eine Person kann mehrere Studenten sein), ABER der JPA-Provider behandelt sie einzigartig, da sie ihre Vererbung kennt. In Objektbeziehungen speichern Sie niemals eine Person, sondern einen Lehrer oder Schüler. Für unterschiedliche Primärschlüssel habe ich meine Antwort für Ihre Bedürfnisse aktualisiert, obwohl Ihr Modell irgendwie verwirrend ist. Ich sehe keine Vorteile durch die Verwendung verschiedener PKs, da diese trotzdem verbunden sind. –

+0

danke für Ihre Zeit, ich bin zu dem Schluss gekommen, dass die Kombination meiner erforderlichen Punkte unmöglich war. Ich habe verschiedene Primärschlüssel aufgegeben und jetzt wird die Datenbank korrekt generiert. Aber das löst mein Problem nicht genau. Ich werde immer noch Ihre Antwort auflösen, um mein Problem teilweise zu lösen. –

Verwandte Themen