Java Hibernate外键必须具有与多对多上引用的主键相同的列数
我试图用JPA实现给定的数据库结构 SQL脚本:Java Hibernate外键必须具有与多对多上引用的主键相同的列数,java,sql,hibernate,Java,Sql,Hibernate,我试图用JPA实现给定的数据库结构 SQL脚本: DROP TABLE IF EXISTS StudentLesson; DROP TABLE IF EXISTS StudentCourse; DROP TABLE IF EXISTS Lesson; DROP TABLE IF EXISTS Course; DROP TABLE IF EXISTS Student; CREATE TABLE IF NOT EXISTS Course ( courseId BIGINT
DROP TABLE IF EXISTS StudentLesson;
DROP TABLE IF EXISTS StudentCourse;
DROP TABLE IF EXISTS Lesson;
DROP TABLE IF EXISTS Course;
DROP TABLE IF EXISTS Student;
CREATE TABLE IF NOT EXISTS Course
(
courseId BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(150) NOT NULL,
description TEXT NULL,
actual TINYINT NOT NULL DEFAULT 1,
PRIMARY KEY (courseId)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS Lesson
(
lessonId BIGINT NOT NULL AUTO_INCREMENT,
courseId BIGINT NOT NULL,
name VARCHAR(150) NOT NULL,
orderNumber INTEGER NULL,
actual TINYINT NOT NULL DEFAULT 1,
PRIMARY KEY (lessonId),
CONSTRAINT FK__Lesson__courseId FOREIGN KEY Lesson (courseId) REFERENCES Course (courseId)
CREATE TABLE IF NOT EXISTS Student
(
studentId BIGINT NOT NULL AUTO_INCREMENT,
userId BIGINT NOT NULL,
PRIMARY KEY (studentId),
CONSTRAINT FK__Student__userId FOREIGN KEY Student (userId) REFERENCES User (userId)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS StudentCourse
(
studentCourseId BIGINT NOT NULL AUTO_INCREMENT,
studentId BIGINT NOT NULL,
courseId BIGINT NOT NULL,
percentCompleted DECIMAL(5, 2) NOT NULL DEFAULT 0.0,
PRIMARY KEY (studentCourseId),
CONSTRAINT FK__StudentCourse__studentId FOREIGN KEY StudentCourse (studentId) REFERENCES Student (studentId),
CONSTRAINT FK__StudentCourse__courseId FOREIGN KEY StudentCourse (courseId) REFERENCES Course (courseId)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS StudentLesson
(
studentLessonId BIGINT NOT NULL AUTO_INCREMENT,
studentCourseId BIGINT NOT NULL,
lessonId BIGINT NOT NULL,
percentCompleted DECIMAL(5, 2) NOT NULL DEFAULT 0.0,
PRIMARY KEY (studentLessonId),
CONSTRAINT FK__StudentLesson__studentCourseId FOREIGN KEY StudentLesson (studentCourseId) REFERENCES StudentCourse (studentCourseId),
CONSTRAINT FK__StudentLesson__lessonId FOREIGN KEY StudentLesson (lessonId) REFERENCES Lesson (lessonId)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci;
以下是我的实体类:
学生
学生课程
@Entity
@Table(name = "StudentCourse")
@Getter
@Setter
public class StudentCourseDBO extends AbstractDBO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "studentCourseId", nullable = false)
private Long studentCourseId;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "studentId", nullable = false)
private StudentDBO student;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "courseId", nullable = false)
private CourseDBO course;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "studentCourse")
private Set<StudentLessonDBO> studentLessons;
@Column(name = "percentCompleted", nullable = false)
private BigDecimal percentCompleted;
}
当我尝试启动我的应用程序时,它会给我错误的外键(FKR8CMXBJOTBR91MTV62SAKWVA:StudentLesson[studentCourseId])必须与引用的主键(StudentCourse[studentId,courseId])具有相同的列数。
完整堆栈跟踪:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.hibernate.MappingException: Foreign key (FKr8cmxbjotnbr91mtv62sakwva:StudentLesson [studentCourseId])) must have same number of columns as the referenced primary key (StudentCourse [studentId,courseId])
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:609) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330) ~[spring-beans-5.3.1.jar:5.3.1]
... 28 common frames omitted
Caused by: org.hibernate.MappingException: Foreign key (FKr8cmxbjotnbr91mtv62sakwva:StudentLesson [studentCourseId])) must have same number of columns as the referenced primary key (StudentCourse [studentId,courseId])
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:148) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:130) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.secondPassCompileForeignKeys(InFlightMetadataCollectorImpl.java:1929) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.secondPassCompileForeignKeys(InFlightMetadataCollectorImpl.java:1845) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1665) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:286) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1224) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1255) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.1.jar:5.3.1]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.1.jar:5.3.1]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.1.jar:5.3.1]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
可能是什么问题?我是否使用多对多关系表StudentCourse错误?错误表明,StudentLesson必须有多个列引用,但在数据库中StudentCourse只有一个主键列(studentCourseId),而不是(studentId,courseId)。AbstractDBO看起来怎么样?也许您也在那里声明了一个id?AbstractDBO看起来怎么样?可能您也在那里声明了一个id?您确定您的数据库没有处于过时状态“如果不存在,创建表”?是的,我每次都在执行DROP TABLE IF EXISTS。我更新了我的问题您确定您的数据库没有处于过时状态“如果不存在创建表”?是的,我每次都在执行DROP TABLE IF EXISTS。我更新了我的问题它只是一个实现Serializable的空抽象类问题是表
StudentCourse
的Hibernate模型有两列作为主键,所以这是您这边的映射问题。是否将表映射到多个实体?或者你有一个@ManyToMany
的地方,你使用StudentCourse
作为联接表吗?StudentCourse是学生和课程之间多对多关系的产物。通常情况下,StudentCourseDBO类甚至不会被创建,但我想将其作为一个单独的实体使用,并带有额外的字段和关系,在这种情况下,StudentLesson是一对多的。有没有办法将主键指定为一个ID字段而不是两个多对多关系字段?我不明白你在做什么,请用所有细节更新你的问题。无论如何,您不能以这种方式多次映射表。如果您将一个表映射为实体,则在希望映射到该表时应始终使用该实体,否则会出现类似这样的问题。它只是一个实现Serializable的空抽象类问题在于表的Hibernate模型StudentCourse
有两列作为主键,所以这是你们这边的一个映射问题。是否将表映射到多个实体?或者你有一个@ManyToMany
的地方,你使用StudentCourse
作为联接表吗?StudentCourse是学生和课程之间多对多关系的产物。通常情况下,StudentCourseDBO类甚至不会被创建,但我想将其作为一个单独的实体使用,并带有额外的字段和关系,在这种情况下,StudentLesson是一对多的。有没有办法将主键指定为一个ID字段而不是两个多对多关系字段?我不明白你在做什么,请用所有细节更新你的问题。无论如何,您不能以这种方式多次映射表。如果将表映射为实体,则在希望映射到该表时应始终使用该实体,否则会出现类似这样的问题。
@Entity
@Table(name = "Lesson")
@Getter
@Setter
public class LessonDBO extends AbstractOrderedDBO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "lessonId", nullable = false)
private Long lessonId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "courseId", nullable = false)
private CourseDBO course;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "actual")
private Boolean actual;
}
@Entity
@Table(name = "StudentCourse")
@Getter
@Setter
public class StudentCourseDBO extends AbstractDBO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "studentCourseId", nullable = false)
private Long studentCourseId;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "studentId", nullable = false)
private StudentDBO student;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "courseId", nullable = false)
private CourseDBO course;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "studentCourse")
private Set<StudentLessonDBO> studentLessons;
@Column(name = "percentCompleted", nullable = false)
private BigDecimal percentCompleted;
}
@Entity
@Table(name = "StudentLesson")
@Getter
@Setter
public class StudentLessonDBO extends AbstractDBO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "studentLessonId", nullable = false)
private Long studentLessonId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "studentCourseId", nullable = false)
private StudentCourseDBO studentCourse;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "lessonId", nullable = false)
private LessonDBO lesson;
@Column(name = "percentCompleted", nullable = false)
private BigDecimal percentCompleted;
}
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.hibernate.MappingException: Foreign key (FKr8cmxbjotnbr91mtv62sakwva:StudentLesson [studentCourseId])) must have same number of columns as the referenced primary key (StudentCourse [studentId,courseId])
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:609) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330) ~[spring-beans-5.3.1.jar:5.3.1]
... 28 common frames omitted
Caused by: org.hibernate.MappingException: Foreign key (FKr8cmxbjotnbr91mtv62sakwva:StudentLesson [studentCourseId])) must have same number of columns as the referenced primary key (StudentCourse [studentId,courseId])
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:148) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:130) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.secondPassCompileForeignKeys(InFlightMetadataCollectorImpl.java:1929) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.secondPassCompileForeignKeys(InFlightMetadataCollectorImpl.java:1845) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1665) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:286) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1224) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1255) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.1.jar:5.3.1]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.1.jar:5.3.1]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.1.jar:5.3.1]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]