一对多多列联接 Spring 数据 JPA
One to Many Multi Column Join Spring Data JPA
我有一个实体 Event
和 Category
。每个 Event
可以有多个 Category
并且一个类别属于一个事件。在 Event
实体中,我有 ageLevelsAllowed
(允许的年龄级别列表)和 genders
(性别列表)基于创建类别并将其映射到锦标赛。
例如,如果列表中有年龄级别 U10 和 U20,性别 M 和 F,我想为事件 E1 创建 4 个类别,
E1 类别 1 U10 M
E1 类别 2 U10 F
E1 类别 3 U20 M
E1 类别 4 U20 F
目前,我的活动实体如下所示 -
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.util.Date;
import java.util.List;
import java.util.Set;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name="TBL_EVENT", uniqueConstraints = {
@UniqueConstraint(columnNames = "name")
})
public class Event {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private int id;
@NotBlank
@Column(name = "name",unique=true)
private String name;
@NotBlank
@ElementCollection
@CollectionTable(name = "event_ageLevels", joinColumns = @JoinColumn(name = "id"))
@Column(name = "ageLevels")
private Set<AgeLevel> ageLevels;
@NotBlank
@ElementCollection
@CollectionTable(name = "event_genders", joinColumns = @JoinColumn(name = "id"))
@Column(name = "genders")
private Set<Gender> genders;
@NotBlank
@DateTimeFormat
private String registrationEndDate;
@OneToMany(mappedBy = "event")
private Set<Category> categories;
}
类别实体是这样定义的。
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
@Table(name="TBL_Categories")
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private int category_id;
@NotBlank
private String categoryName;
@ManyToOne
@JsonIgnore
@JoinColumns({
@JoinColumn(name="id", nullable = false),
@JoinColumn(name="ageLevels", nullable = false),
@JoinColumn(name="genders", nullable = false)
})
private Event event;
}
当我尝试执行此操作以创建具有三个外键引用的表时,出现如下错误。
2021-11-24 00:58:58.050 ERROR 31404 --- [ main] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: A Foreign key refering com.proj.entity.Event from com.proj.entity.Category has the wrong number of column. should be 1
2021-11-24 00:58:58.050 ERROR 31404 --- [ main] o.s.b.web.embedded.tomcat.TomcatStarter : Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: Error creating bean with name 'jwtFilter': Unsatisfied dependency expressed through field 'groupUserDetailsService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'groupUserDetailsService': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository' defined in com.proj.repository.UserRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot create inner bean '(inner bean)#465b38e6' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#465b38e6': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: A Foreign key refering com.ser515.proj.entity.Event from com.proj.entity.Category has the wrong number of column. should be 1
2021-11-24 00:58:58.067 INFO 31404 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2021-11-24 00:58:58.068 WARN 31404 --- [ main] o.a.c.loader.WebappClassLoaderBase : The web application [ROOT] appears to have started a thread named [HikariPool-1 housekeeper] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.base@15.0.2/jdk.internal.misc.Unsafe.park(Native Method)
您在这部分遇到问题:
@JoinColumns({
@JoinColumn(name="id", nullable = false),
@JoinColumn(name="ageLevels", nullable = false),
@JoinColumn(name="genders", nullable = false)
})
private Event event;
在您的情况下,Event 的主键应该是复合主键,因此您需要使用带有 id、ageLevels 和 genders 的 @EmbeddedId 作为主键。
这个答案可以帮助:
我有一个实体 Event
和 Category
。每个 Event
可以有多个 Category
并且一个类别属于一个事件。在 Event
实体中,我有 ageLevelsAllowed
(允许的年龄级别列表)和 genders
(性别列表)基于创建类别并将其映射到锦标赛。
例如,如果列表中有年龄级别 U10 和 U20,性别 M 和 F,我想为事件 E1 创建 4 个类别,
E1 类别 1 U10 M
E1 类别 2 U10 F
E1 类别 3 U20 M
E1 类别 4 U20 F
目前,我的活动实体如下所示 -
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.util.Date;
import java.util.List;
import java.util.Set;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name="TBL_EVENT", uniqueConstraints = {
@UniqueConstraint(columnNames = "name")
})
public class Event {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private int id;
@NotBlank
@Column(name = "name",unique=true)
private String name;
@NotBlank
@ElementCollection
@CollectionTable(name = "event_ageLevels", joinColumns = @JoinColumn(name = "id"))
@Column(name = "ageLevels")
private Set<AgeLevel> ageLevels;
@NotBlank
@ElementCollection
@CollectionTable(name = "event_genders", joinColumns = @JoinColumn(name = "id"))
@Column(name = "genders")
private Set<Gender> genders;
@NotBlank
@DateTimeFormat
private String registrationEndDate;
@OneToMany(mappedBy = "event")
private Set<Category> categories;
}
类别实体是这样定义的。
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
@Table(name="TBL_Categories")
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private int category_id;
@NotBlank
private String categoryName;
@ManyToOne
@JsonIgnore
@JoinColumns({
@JoinColumn(name="id", nullable = false),
@JoinColumn(name="ageLevels", nullable = false),
@JoinColumn(name="genders", nullable = false)
})
private Event event;
}
当我尝试执行此操作以创建具有三个外键引用的表时,出现如下错误。
2021-11-24 00:58:58.050 ERROR 31404 --- [ main] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: A Foreign key refering com.proj.entity.Event from com.proj.entity.Category has the wrong number of column. should be 1
2021-11-24 00:58:58.050 ERROR 31404 --- [ main] o.s.b.web.embedded.tomcat.TomcatStarter : Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: Error creating bean with name 'jwtFilter': Unsatisfied dependency expressed through field 'groupUserDetailsService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'groupUserDetailsService': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository' defined in com.proj.repository.UserRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot create inner bean '(inner bean)#465b38e6' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#465b38e6': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: A Foreign key refering com.ser515.proj.entity.Event from com.proj.entity.Category has the wrong number of column. should be 1
2021-11-24 00:58:58.067 INFO 31404 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2021-11-24 00:58:58.068 WARN 31404 --- [ main] o.a.c.loader.WebappClassLoaderBase : The web application [ROOT] appears to have started a thread named [HikariPool-1 housekeeper] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.base@15.0.2/jdk.internal.misc.Unsafe.park(Native Method)
您在这部分遇到问题:
@JoinColumns({
@JoinColumn(name="id", nullable = false),
@JoinColumn(name="ageLevels", nullable = false),
@JoinColumn(name="genders", nullable = false)
})
private Event event;
在您的情况下,Event 的主键应该是复合主键,因此您需要使用带有 id、ageLevels 和 genders 的 @EmbeddedId 作为主键。
这个答案可以帮助: