簡體   English   中英

Hibernate / JPA如何解決子類錯誤生成數據庫表的問題

[英]Hibernate/JPA How to fix wrong generation of database tables from subclasses

通過JPA和Hibernate批注在數據庫中生成表時遇到了一些困難。

執行以下代碼時,它將使用以下EER圖生成表。

生成的人,學生和老師的EER圖

這不是我希望它生成表的方式。 首先,表之間的關系是錯誤的,它們必須是OneToOne而不是OneToMany。 其次,我不希望電子郵件成為學生和老師的主鍵。

在學生中,ovNumber應該是主鍵,在教師中,employeeNumber是我嘗試使用@Id注釋執行的操作,但這給了我以下錯誤:

org.hibernate.mapping.JoinedSubclass無法轉換為org.hibernate.mapping.RootClass

當我嘗試使用@MappedSuperClass時,即使使用@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) ,表人也不會生成。

現在我的問題是

如何在子類的子表中使另一個變量成為對應表的主鍵,同時又將超類的主鍵保留為外鍵?

如何將表之間的關系固定為OneToOne關系而不是OneToMany關系?

這是應有的EER圖。

人,學生和教師的EER圖應采用的方式

以下是用於生成表的模型類。

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

您的目標是實現繼承,其中Person是您的超類。 TeacherStudent是其中的子類。 JPA中的繼承與它的sql實現不同。 我建議閱讀下面我剛才寫的答案 另請閱讀JavaEE 7-實體繼承教程

##編輯##

這是您針對每個實體使用不同主鍵的解決方案,但我仍然認為這是不尋常的設計(其他設計請參考原始消息):

人:

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

學生

@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-entities。 將人聲明為抽象實體,並按人擴展教師和學生。

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
}

在老師和學生中嘗試這個

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

代替 :

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM