natyus
natyus

Reputation: 647

How to map oneTomany and manyToone correctly in spring boot

I have two Entities which have a bidirectional relationship the Entity class:

MeetingsSetting:

@Entity
@Table(name = "meeting_settings")
public class MeetingsSetting {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "meeting_name")
    private String meetingName;

    @Column(name = "meeting_url")
    private String meetingUrl;

    @Column(name = "meeting_pw")
    private String meetingPw;

    @OneToMany(mappedBy = "meetingsSetting", cascade = CascadeType.ALL)
    private Set<Date> dates = new HashSet<>();

    @OneToMany(mappedBy = "meetingsSetting", cascade = CascadeType.ALL)
    private List<Time> times = new ArrayList<>();

With the configuration class:

@Configuration
@PropertySource({"classpath:persistence-multiple-db.properties"})
@EnableJpaRepositories(
        basePackages = "com.cbc.coorporateblinddateservice.repositories.meetinsSetting",
        entityManagerFactoryRef = "meetingSettingEntityManager",
        transactionManagerRef = "meetingSettingTransactionManager"
)
public class MeetingSettingsConfig {

    @Autowired
    private Environment env;

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean meetingSettingEntityManager() {
        LocalContainerEntityManagerFactoryBean em
                = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(meetingSettingDataSource());
        em.setPackagesToScan(
                "com.cbc.coorporateblinddateservice.entities.meetinsSetting");

        HibernateJpaVendorAdapter vendorAdapter
                = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        HashMap<String, Object> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.create",
                env.getProperty("meetingSetting.hibernate.hbm2ddl"));
        properties.put("hibernate.dialect",
                env.getProperty("hibernate.dialect"));
        em.setJpaPropertyMap(properties);

        return em;
    }

    @Primary
    @Bean
    public DataSource meetingSettingDataSource() {

        DriverManagerDataSource dataSource
                = new DriverManagerDataSource();
        dataSource.setDriverClassName(
                env.getProperty("meetingSetting.jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("meetingSetting.jdbc.url"));
        dataSource.setUsername(env.getProperty("meetingSetting.jdbc.user"));
        dataSource.setPassword(env.getProperty("meetingSetting.jdbc.pass"));
        dataSource.setSchema("coorporate_blinddate");

        return dataSource;
    }

    @Primary
    @Bean
    public PlatformTransactionManager meetingSettingTransactionManager() {

        JpaTransactionManager transactionManager
                = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(
                meetingSettingEntityManager().getObject());
        return transactionManager;
    }

and the Date entity:

@Entity
@Table(name = "meeting_date")
public class Date {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "meeting_date")
    private String date;

    @OneToMany(mappedBy = "meetingDate", cascade = CascadeType.ALL)
    private List<Time> meetingTime = new ArrayList<>();

    @ManyToOne(targetEntity = MeetingsSetting.class)
    @JoinColumn(name = "meeting_settings_id", nullable = false)
    private MeetingsSetting meetingsSetting;

}

Config class:

@Configuration
@PropertySource({"classpath:persistence-multiple-db.properties"})
@EnableJpaRepositories(
        basePackages = "com.cbc.coorporateblinddateservice.repositories.dates",
        entityManagerFactoryRef = "meetingDateEntityManager",
        transactionManagerRef = "meetingDateTransactionManager"
)
public class MeetingDateConfig {

    @Autowired
    private Environment env;

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean meetingDateEntityManager() {
        LocalContainerEntityManagerFactoryBean em
                = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(meetingDateDataSource());
        em.setPackagesToScan(
                "com.cbc.coorporateblinddateservice.entities.dates");

        HibernateJpaVendorAdapter vendorAdapter
                = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        HashMap<String, Object> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.create",
                env.getProperty("meetingDate.hibernate.hbm2ddl"));
        properties.put("hibernate.dialect",
                env.getProperty("hibernate.dialect"));
        em.setJpaPropertyMap(properties);

        return em;
    }

    @Primary
    @Bean
    public DataSource meetingDateDataSource() {

        DriverManagerDataSource dataSource
                = new DriverManagerDataSource();
        dataSource.setDriverClassName(
                env.getProperty("meetingDate.jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("meetingDate.jdbc.url"));
        dataSource.setUsername(env.getProperty("meetingDate.jdbc.user"));
        dataSource.setPassword(env.getProperty("meetingDate.jdbc.pass"));
        dataSource.setSchema("coorporate_blinddate");

        return dataSource;
    }

    @Primary
    @Bean
    public PlatformTransactionManager meetingDateTransactionManager() {

        JpaTransactionManager transactionManager
                = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(
                meetingDateEntityManager().getObject());
        return transactionManager;
    }

If I know try to start my application I am getting the following error:

Caused by: org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.cbc.coorporateblinddateservice.entities.dates.Date.meetingsSetting references an unknown entity: com.cbc.coorporateblinddateservice.entities.meetinsSetting.MeetingsSetting
    at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:100) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processEndOfQueue(InFlightMetadataCollectorImpl.java:1823) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processFkSecondPassesInOrder(InFlightMetadataCollectorImpl.java:1767) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1655) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:295) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1224) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1255) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final]

I looked at several posts here suggesting to correct the import of Entity annotation (Java.persistence, and setting targetClass by manyToone) and examples which do it completely like me, but none of it helped me. Could someone look at my code and tell me what could possibly be wrong?

Upvotes: 1

Views: 261

Answers (1)

Guillaume
Guillaume

Reputation: 14656

Hibernate needs to know where to look for entity classes.

You're doing em.setPackagesToScan("com.cbc.coorporateblinddateservice.entities.dates") But MeetingsSetting is in the com.cbc.coorporateblinddateservice.entities.meetinsSetting package, so you need to scan that package too.

Upvotes: 1

Related Questions