Java Hibernate/JPA如何修复从子类错误生成的数据库表
我在通过JPA和Hibernate注释在数据库中生成表时遇到了一些困难 当执行下面的代码时,它生成具有以下EER图的表 这不是我希望它生成表的方式。 首先,表之间的关系是错误的,它们必须是一对一而不是一对一。 第二,我不想让电子邮件成为学生和老师的主键 在学生中,ovNumber应为主键,在教师中,ovNumber应为employeeNumber 我曾尝试使用Java Hibernate/JPA如何修复从子类错误生成的数据库表,java,hibernate,jpa,Java,Hibernate,Jpa,我在通过JPA和Hibernate注释在数据库中生成表时遇到了一些困难 当执行下面的代码时,它生成具有以下EER图的表 这不是我希望它生成表的方式。 首先,表之间的关系是错误的,它们必须是一对一而不是一对一。 第二,我不想让电子邮件成为学生和老师的主键 在学生中,ovNumber应为主键,在教师中,ovNumber应为employeeNumber 我曾尝试使用@Id注释执行此操作,但出现以下错误: org.hibernate.mapping.JoinedSubclass不能强制转换为org.h
@Id
注释执行此操作,但出现以下错误:
org.hibernate.mapping.JoinedSubclass不能强制转换为org.hibernate.mapping.RootClass
当我尝试使用@MappedSuperClass
时,即使使用@heritance(strategy=heritancetype.table\u PER\u CLASS)
时,表person也不会生成
现在我的问题是,
如何使子类中的另一个变量成为腐蚀表的主键,同时将超类主键保留为外键
如何将表之间的关系固定为一对一关系而不是一对一关系
下面是一个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());
}
}
@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 + "]";
}
}
@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() + "]";
}
}
Student.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());
}
}
@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 + "]";
}
}
@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() + "]";
}
}
在老师和学生身上试试这个
@OneToOne
@PrimaryKeyJoinColumn(name="person_email", referencedColumnName="email")
private Person preson;
而不是:
@PrimaryKeyJoinColumn(name="email", referencedColumnName="email")
您的目标是实现继承,其中
Person
是您的超类Teacher
和Student
是其中的子类。JPA中的继承与sql实现不同。我建议你读一下我刚才写的东西。也读
###编辑##
以下是针对您所要求的每个实体的不同主键的解决方案,但我认为这是一种不同寻常的设计(对于其他实体,请参考原始消息):
人:
@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实体。将人声明为抽象实体,将教师和学生逐个扩展 示例代码: 人
@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
}
这似乎不起作用,我知道如果不扩展Person类,这是一种方法。然而,老师和学生都扩展了Person类。谢谢你的回答,这似乎并没有做我想要的正确的事情。表之间的关系仍然是一对一而不是一对一。此外,我希望避免使用id,因为在这种情况下,电子邮件始终是唯一的值。这也不包括为学生和教师设置不同主键的部分。如果您能编辑您的答案以解决这些问题,我将不胜感激。在它的SQL实现中,它们似乎是一对一(一个人可以是多个学生),但JPA提供商将对它们进行独特处理,因为它知道这是继承。在对象关系中,除了老师或学生,你永远不会拯救一个人。由于有不同的主键,我根据您的需要更新了我的答案,尽管您的模型有些混乱。我认为使用不同的PK没有任何好处,因为它们是相互关联的。感谢您的时间,我得出结论,我所需的积分组合是不可能的。我已经放弃了使用不同的主键,现在它正确地生成了数据库。然而,这并不能完全解决我的问题,我仍然会投票支持你的答案,因为它部分解决了我的问题。