我正在尝试在数据库中建立多对多连接。因为逻辑上类型和语言可以有多本书,反之亦然

I'm trying to establish many-to-many connections in the database. Because logically types and languages can have multiple books and vice versa

 import lombok.Data;

 import javax.persistence.*;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;


 @Entity
 @Data
 @Table(name = "books")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String publisher;
private String author;
private String aboutBook;
private String fragment;
private int date;
private int volume;
private int quantity;
private int price;
private int discount;
private Boolean bestseller;
private String bookLink;//s3

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "users_books",
        joinColumns = @JoinColumn(name = "book_id"),
        inverseJoinColumns = @JoinColumn(name = "user_id"))
private List<User> users;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "books_genres",
        joinColumns = @JoinColumn(name = "book_id"),
        inverseJoinColumns = @JoinColumn(referencedColumnName = "genre_id"))
private Set<Genre> genres;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "books_languages",
        joinColumns = @JoinColumn(name = "book_id"),
        inverseJoinColumns = @JoinColumn(referencedColumnName = "language_id"))
private Set<Language> languages;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "books_types",
        joinColumns = @JoinColumn(name = "book_id"),
        inverseJoinColumns = @JoinColumn(referencedColumnName = "type_id"))
private Set<Type> types;



public Optional<String> getBookLink() {
    return Optional.ofNullable(bookLink);
}

public void setBookLink(String bookLink) {
    this.bookLink = bookLink;
}


@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Book book = (Book) o;
    return date == book.date &&
            volume == book.volume &&
            quantity == book.quantity &&
            price == book.price &&
            discount == book.discount &&
            id.equals(book.id) &&
            name.equals(book.name) &&
            publisher.equals(book.publisher) &&
            author.equals(book.author) &&
            aboutBook.equals(book.aboutBook) &&
            fragment.equals(book.fragment) &&
            bestseller.equals(book.bestseller)
            && users.equals(book.users);
}

@Override
public int hashCode() {
    return Objects.hash(id, name, publisher, author, aboutBook, fragment, date, volume, quantity, price, discount, bestseller, users);
}

 } 

@Entity
@Data
@Table(name = "genres")
public class Genre {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@ManyToMany(mappedBy = "genres")
private List<Book> books;
}

 @Entity
 @Data
 @Table(name = "languages")
 public class Language {
 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Long id;

 private String name;

 @ManyToMany(mappedBy = "languages")
 private List<Book> books;
 }

@Entity
@Data
@Table(name = "types")
public class Type {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
@ManyToMany(mappedBy = "types")
private List<Book> books;

}

@Entity
@Data
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;

@Column(name = "username")
private String username;
@Column(name = "last_name")
private String lastName;

@Column(name = "password")
private String password;

@Column(name = "email")
private String email;

@Column(name = "number_of_phone")
private Long number;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "users_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;

public Set<Role> getRoles() {
    return roles;
}

public void setRoles(Set<Role> roles) {
    this.roles = roles;
}

}

但是我收到这个错误


   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.cfg.RecoverableException: Unable to find column with logical name: type_id in org.hibernate.mapping.Table(types) and its related supertables and secondary tables
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=15=](AbstractBeanFactory.java:335) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154) ~[spring-context-5.3.16.jar:5.3.16]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908) ~[spring-context-5.3.16.jar:5.3.16]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.16.jar:5.3.16]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) [spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) [spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) [spring-boot-2.6.4.jar:2.6.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) [spring-boot-2.6.4.jar:2.6.4]
at com.ebook.EBookApplication.main(EBookApplication.java:10) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_311]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_311]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_311]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_311]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.6.4.jar:2.6.4]
Caused by: org.hibernate.cfg.RecoverableException: Unable to find column with logical name: type_id in org.hibernate.mapping.Table(types) and its related supertables and secondary tables
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:844) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:126) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.cfg.annotations.CollectionBinder.bindManytoManyInverseFk(CollectionBinder.java:1802) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1679) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:874) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.cfg.annotations.CollectionBinder.secondPass(CollectionBinder.java:799) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:53) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1653) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1629) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:295) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1460) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1494) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.16.jar:5.3.16]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.16.jar:5.3.16]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.16.jar:5.3.16]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-5.3.16.jar:5.3.16]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.16.jar:5.3.16]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.16.jar:5.3.16]
... 21 common frames omitted
Caused by: org.hibernate.MappingException: Unable to find column with logical name: type_id in org.hibernate.mapping.Table(types) and its related supertables and secondary tables
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:839) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
... 39 common frames omitted`

referencedColumnName 值应与引用 class 字段值相同。查看Type class/entity的字段,没有field/variable type_id,只有id field/variable存在,所以你应该引用列名作为 id.

其他字段按此方式计费

@Entity
@Data
@Table(name = "books")
public class Book {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;

   @ManyToMany(fetch = FetchType.EAGER)
   @JoinTable(name = "books_types",
        joinColumns = @JoinColumn(name = "book_id"),
        inverseJoinColumns = @JoinColumn(referencedColumnName = "id")
   )
   private Set<Type> types;

} 

_

@Entity
@Data
@Table(name = "types")
public class Type {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;

   private String name;

   @ManyToMany(mappedBy = "types")
   private List<Book> books;

}