[英]Hibernate/JPA How to fix wrong generation of database tables from subclasses
通過JPA和Hibernate批注在數據庫中生成表時遇到了一些困難。
執行以下代碼時,它將使用以下EER圖生成表。
這不是我希望它生成表的方式。 首先,表之間的關系是錯誤的,它們必須是OneToOne而不是OneToMany。 其次,我不希望電子郵件成為學生和老師的主鍵。
在學生中,ovNumber應該是主鍵,在教師中,employeeNumber是我嘗試使用@Id
注釋執行的操作,但這給了我以下錯誤:
org.hibernate.mapping.JoinedSubclass無法轉換為org.hibernate.mapping.RootClass
當我嘗試使用@MappedSuperClass
時,即使使用@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
,表人也不會生成。
現在我的問題是
如何在子類的子表中使另一個變量成為對應表的主鍵,同時又將超類的主鍵保留為外鍵?
如何將表之間的關系固定為OneToOne關系而不是OneToMany關系?
這是應有的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
是您的超類。 Teacher
和Student
是其中的子類。 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.