Spring Hibernate - член класса дважды используется в качестве внешнего ключа - PullRequest
1 голос
/ 05 мая 2020

Я программирую "похожее на 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 {

     ...

}

1 Ответ

0 голосов
/ 06 мая 2020

Трек-лист абстрактных классов

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "TrackList_Track", 
joinColumns = @JoinColumn(name = "tlid",referencedColumnName = "name of the ref"), 
inverseJoinColumns = @JoinColumn(name = "tid",referencedColumnName = "name of the ref"))
@OneToMany(mappedBy = "album")
private List<Track> trackList;

та же проблема для всех многих и alah aalam

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...