我正在我的类上使用 SpringDataJPA 和 Hibernate 映射开发 Spring Boot 应用程序,但遇到以下问题。
首先我有这个Project实体类:
@Entity
@Table(name = "project")
public class Project {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "project_name", nullable = false)
private String projectName;
@Column(name = "code", nullable = false)
private String projectCode;
@Column(name = "description")
private String description;
@Column(name = "start_date", nullable = false)
@Temporal(TemporalType.DATE)
private LocalDate startDate;
@Column(name = "end_date", nullable = false)
@Temporal(TemporalType.DATE)
private LocalDate endDate;
@Column(name = "budget", nullable = false, precision = 10, scale = 2)
private BigDecimal budget;
@ManyToOne
@JoinColumn(name = "client_id_fk", referencedColumnName = "id", nullable = false)
private Client client;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "project_supplier",
joinColumns = @JoinColumn(name = "project_id"),
inverseJoinColumns = @JoinColumn(name = "supplier_id")
)
private Set<Supplier> suppliers = new HashSet<>();
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getProjectName() {
return projectName;
}
public String getProjectCode() {
return projectCode;
}
public void setProjectCode(String projectCode) {
this.projectCode = projectCode;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public LocalDate getStartDate() {
return startDate;
}
public void setStartDate(LocalDate startDate) {
this.startDate = startDate;
}
public LocalDate getEndDate() {
return endDate;
}
public void setEndDate(LocalDate endDate) {
this.endDate = endDate;
}
public BigDecimal getBudget() {
return budget;
}
public void setBudget(BigDecimal budget) {
this.budget = budget;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public Set<Supplier> getSuppliers() {
return suppliers;
}
public void setSuppliers(Set<Supplier> suppliers) {
this.suppliers = suppliers;
}
@Override
public String toString() {
return "Project [id=" + id + ", projectName=" + projectName + ", description=" + description + ", startDate="
+ startDate + ", endDate=" + endDate + ", budget=" + budget + ", client=" + client + "]";
}
}
如您所见,它包含与 Supplier 实体的多对多关系:
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "project_supplier",
joinColumns = @JoinColumn(name = "project_id"),
inverseJoinColumns = @JoinColumn(name = "supplier_id")
)
private Set<Supplier> suppliers = new HashSet<>();
这是我的project_supplier关系表:
p”寻求帮助。
gestionale_interno_db=# \d project_suplier
Did not find any relation named "project_suplier".
gestionale_interno_db=# \d project_supplier
Table "public.project_supplier"
Column | Type | Collation | Nullable | Default
-------------+---------------+-----------+----------+----------------------------------
id | bigint | | not null | generated by default as identity
project_id | bigint | | not null |
supplier_id | bigint | | not null |
notes | text | | |
daily_rate | numeric(10,2) | | not null |
Indexes:
"project_supplier_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"project_supplier_project_id_fkey" FOREIGN KEY (project_id) REFERENCES project(id)
"project_supplier_supplier_id_fkey" FOREIGN KEY (supplier_id) REFERENCES supplier(id)
这个效果很好。当我将等效的 ManyToMany 关系引入到我的 Supplier 实体类中时,就会出现问题:
@Entity
@Table(name = "supplier")
public class Supplier {
private long id;
private String name;
private String vatNumber;
private String address;
private String email;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "project_supplier",
joinColumns = @JoinColumn(name = "supplier_id"),
inverseJoinColumns = @JoinColumn(name = "project_id")
)
private Set<Project> projects = new HashSet<>();
public Supplier() {
super();
}
public Supplier(String name, String vatNumber, String address, String email) {
super();
this.name = name;
this.vatNumber = vatNumber;
this.address = address;
this.email = email;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "vat_number", nullable = false)
public String getVatNumber() {
return vatNumber;
}
public void setVatNumber(String vatNumber) {
this.vatNumber = vatNumber;
}
@Column(name = "address", nullable = false)
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Set<Project> getProjects() {
return projects;
}
public void setProjects(Set<Project> projects) {
this.projects = projects;
}
@Override
public String toString() {
return "Supplier [id=" + id + ", name=" + name + ", vatNumber=" + vatNumber + ", address=" + address
+ ", email=" + email + ", projects=" + projects + "]";
}
}
事实上,当我将此关系添加到第二个实体类中时:
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "project_supplier",
joinColumns = @JoinColumn(name = "supplier_id"),
inverseJoinColumns = @JoinColumn(name = "project_id")
)
private Set<Project> projects = new HashSet<>();
运行我的应用程序时出现此异常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Could not determine recommended JdbcType for `com.fivebits.gestionale.model.entity.Project`
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770) ~[spring-beans-6.0.12.jar:6.0.12]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[spring-beans-6.0.12.jar:6.0.12]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.12.jar:6.0.12]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.0.12.jar:6.0.12]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.12.jar:6.0.12]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.0.12.jar:6.0.12]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.0.12.jar:6.0.12]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1158) ~[spring-context-6.0.12.jar:6.0.12]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) ~[spring-context-6.0.12.jar:6.0.12]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) ~[spring-context-6.0.12.jar:6.0.12]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.1.4.jar:3.1.4]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) ~[spring-boot-3.1.4.jar:3.1.4]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-3.1.4.jar:3.1.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-3.1.4.jar:3.1.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) ~[spring-boot-3.1.4.jar:3.1.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) ~[spring-boot-3.1.4.jar:3.1.4]
at com.fivebits.gestionale.GestionaleInternoApplication.main(GestionaleInternoApplication.java:10) ~[classes/:na]
Caused by: org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException: Could not determine recommended JdbcType for `com.fivebits.gestionale.model.entity.Project`
at org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType.getRecommendedJdbcType(UnknownBasicJavaType.java:37) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.hibernate.type.descriptor.java.spi.BasicCollectionJavaType.getRecommendedJdbcType(BasicCollectionJavaType.java:74) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.hibernate.boot.model.process.internal.InferredBasicValueResolver.from(InferredBasicValueResolver.java:222) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.hibernate.mapping.BasicValue.buildResolution(BasicValue.java:480) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.hibernate.mapping.BasicValue.resolve(BasicValue.java:310) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.hibernate.mapping.BasicValue.resolve(BasicValue.java:300) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.lambda$processValueResolvers$4(InFlightMetadataCollectorImpl.java:1855) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at java.base/java.util.ArrayList.removeIf(ArrayList.java:1682) ~[na:na]
at java.base/java.util.ArrayList.removeIf(ArrayList.java:1660) ~[na:na]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processValueResolvers(InFlightMetadataCollectorImpl.java:1854) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1840) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:331) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1380) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1451) ~[hibernate-core-6.2.9.Final.jar:6.2.9.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[spring-orm-6.0.12.jar:6.0.12]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) ~[spring-orm-6.0.12.jar:6.0.12]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.0.12.jar:6.0.12]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.0.12.jar:6.0.12]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) ~[spring-orm-6.0.12.jar:6.0.12]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1817) ~[spring-beans-6.0.12.jar:6.0.12]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) ~[spring-beans-6.0.12.jar:6.0.12]
... 16 common frames omitted
为什么会出现这个错误?怎么了?我该如何解决它?
根据项目实体中的 JPA 标准,无需再次指定父关系,只需:
@ManyToMany(mappedBy = "suppliers")
private Set<Project> projects = new HashSet<>();
在这里您可以找到详尽的指南:JPA 中的多对多关系
希望对你有帮助。