Я программирую "похожее на Deezer" приложение для учебы, и у меня возникла проблема с отображением внешних ключей. Вот код:
Трек-лист абстрактного класса
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "list_type")
public abstract class TrackList {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int tlid;
private String name;
private String imageFileName;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "TrackList_Track", joinColumns = @JoinColumn(name = "tlid"), inverseJoinColumns =
@JoinColumn(name = "tid"))
@OneToMany(mappedBy = "album")
private ArrayList<Track> trackList = new ArrayList<>();
...
}
Альбом класса расширяет трек-лист
@Entity
@DiscriminatorValue("ALBUM")
public class Album extends TrackList {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int aid;
private LocalDate date;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "Album_Genre", joinColumns = @JoinColumn(name = "aid"), inverseJoinColumns =
@JoinColumn(name = "gid"))
private ArrayList<Genre> genres = new ArrayList<>();
@ManyToMany(mappedBy = "albums")
private ArrayList<Performer> performers = new ArrayList<>();
...
}
Класс Плейлист расширяет список треков
@Entity
@DiscriminatorValue("PLAYLIST")
public class Playlist extends TrackList {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int plid;
private User creator;
private String description;
@ManyToMany(mappedBy = "playlists")
private ArrayList<User> users;
...
}
Класс Трек
@Entity
public class Track {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int tid;
private String mp3FileName;
@ManyToOne
@JoinColumn(name = "tlid")
private Album album;
private int num = 0;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "Track_Genre", joinColumns = @JoinColumn(name = "tid"), inverseJoinColumns =
@JoinColumn(name = "gid"))
private ArrayList<Genre> genres = new ArrayList<>();
@ManyToMany(mappedBy = "tracklist")
private ArrayList<Performer> performers = new ArrayList<>();
@ManyToMany(mappedBy = "trackList")
private ArrayList<Playlist> playlists = new ArrayList<>();
}
Класс Жанр
@Entity
public class Genre {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int gid;
private String name;
@ManyToMany(mappedBy = "genres")
private ArrayList<Track> tracks = new ArrayList<>();
@ManyToMany(mappedBy = "genres")
private ArrayList<Album> albums = new ArrayList<>();
...
}
Исполнитель класса
@Entity
public class Performer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int peid;
private String name;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "Performer_Album", joinColumns = @JoinColumn(name = "peid"), inverseJoinColumns =
@JoinColumn(name = "aid"))
private ArrayList<Album> albums = new ArrayList<>();
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "Performer_Track", joinColumns = @JoinColumn(name = "peid"), inverseJoinColumns =
@JoinColumn(name = "tid"))
private ArrayList<Track> tracklist = new ArrayList<>();
...
}
Пользователь класса
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "user_type")
@DiscriminatorValue("CLASSIC")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int uid;
private String pseudo;
private String email;
private String password;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "User_Playlist", joinColumns = @JoinColumn(name = "uid"), inverseJoinColumns =
@JoinColumn(name = "plid"))
private ArrayList<Playlist> playlists;
...
}
И вот ошибка, которую я получаю:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-05-05 20:59:00.301 ERROR 21040 --- [ main] o.s.boot.SpringApplication : Application run failed
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: java.util.ArrayList collection type not supported for property: org.ThePouil.projects.MyTunes.model.beans.music.TrackList.trackList
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.ThePouil.projects.MyTunesApplication.main(MyTunesApplication.java:10) [classes/:na]
Caused by: org.hibernate.AnnotationException: java.util.ArrayList collection type not supported for property: org.ThePouil.projects.MyTunes.model.beans.music.TrackList.trackList
at org.hibernate.cfg.annotations.CollectionBinder.getCollectionBinder(CollectionBinder.java:317) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1939) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:975) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:802) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:254) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:230) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:273) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1202) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1233) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:378) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
... 16 common frames omitted
Спасибо за вашу помощь.
:: EDIT :: Очевидно, Hibernate не может обрабатывать ArrayList <> но List <> и спасибо to @ AdyJunior Я удалил поле @ OneToMany в trackList в классе TrackList и создал новое поле в Album класс. Поэтому я изменил свой код на:
Список треков абстрактных классов
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "list_type")
public abstract class TrackList {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int tlid;
private String name;
private String imageFileName;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "TrackList_Track", joinColumns = @JoinColumn(name =
"tlid"), inverseJoinColumns =
@JoinColumn(name = "tid"))
private List<Track> trackList = new ArrayList<>();
...
}
Альбом классов расширяет список треков
@Entity
@DiscriminatorValue("ALBUM")
public class Album extends TrackList {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int aid;
/* a reference to the List<Track> trackList from mother class */
/* overrided getter/setter
@OneToMany(mappedBy = "album")
private List<Track> trackList = new ArrayList<>();
private LocalDate date;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "Album_Genre", joinColumns = @JoinColumn(name = "aid"),
inverseJoinColumns =
@JoinColumn(name = "gid"))
private List<Genre> genres = new ArrayList<>();
@ManyToMany(mappedBy = "albums")
private List<Performer> performers = new ArrayList<>();
...
}
И теперь я получаю ошибку:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-05-06 11:50:05.582 ERROR 17088 --- [ main] o.s.boot.SpringApplication : Application run failed
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 java.lang.ClassCastException: org.hibernate.mapping.JoinedSubclass cannot be cast to org.hibernate.mapping.RootClass
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.ThePouil.projects.MyTunesApplication.main(MyTunesApplication.java:10) [classes/:na]
Caused by: java.lang.ClassCastException: org.hibernate.mapping.JoinedSubclass cannot be cast to org.hibernate.mapping.RootClass
at org.hibernate.cfg.annotations.PropertyBinder.bind(PropertyBinder.java:214) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.cfg.annotations.PropertyBinder.makePropertyValueAndBind(PropertyBinder.java:205) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2282) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:975) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:802) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:254) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:230) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:273) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1202) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1233) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:378) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
... 16 common frames omitted
:: EDIT 2 :: Ну, sub -классы НЕ ДОЛЖНЫ иметь @ ID , только главный класс. Поэтому я удалил @ ID из класса альбома и класса списка воспроизведения . Это устранило предыдущую ошибку. Но теперь я получаю это:
org.hibernate.MappingException: Could not determine type for: packages.User, at table: playlist, for columns: [org.hibernate.mapping.Column(creator)]
:: EDIT 3 :: Чтобы удалить предыдущую ошибку:
Список воспроизведения класса
@ManyToOne
@JoinColumn(name = "uid")
private User creator;
Также добавлен метод для получения "принадлежащих" / созданных списков воспроизведения в Класс пользователя :
@OneToMany(mappedBy = "creator")
public List<Playlist> getOwnPlaylist() {
ArrayList<Playlist> pl = new ArrayList<>();
for (Playlist p : playlists)
try {
if (isCreator(p))
pl.add(p);
} catch (UserException e) {
e.printStackTrace();
}
return pl;
}
Теперь получаются ошибки:
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table playlist add constraint FKpqwn3quei4t1vlr1eh3pt4fts foreign key (uid) references user (uid)" via JDBC Statement
...
java.sql.SQLException: Failed to add the foreign key constraint. Missing index for constraint 'FKpqwn3quei4t1vlr1eh3pt4fts' in the referenced table 'user'
:: РЕДАКТИРОВАТЬ 4 (ПОСЛЕДНИЙ?) :: Ну, это непростой . У вас не может быть таблицы с именем «User», потому что она зарезервирована для mysql / postgresql / et c ... Чтобы удалить предыдущую ошибку:
Class User
@Entity
@Table(name = "MT_User")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "user_type")
@DiscriminatorValue("CLASSIC")
public class User {
...
}