【问题标题】:How to map oneTomany and manyToone correctly in spring boot如何在 Spring Boot 中正确映射 oneTomany 和 manyToone
【发布时间】:2021-05-27 05:23:18
【问题描述】:

我有两个实体,它们与实体类有双向关系:

会议设置:

@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<>();

带配置类:

@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;
    }

和日期实体:

@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;

}

配置类:

@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;
    }

如果我知道尝试启动我的应用程序,我会收到以下错误:

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]

我在这里查看了几篇建议更正实体注释的导入(Java.persistence,并通过 manyToone 设置 targetClass)以及完全像我一样执行此操作的示例,但没有一个对我有帮助。有人可以看看我的代码并告诉我可能有什么问题吗?

【问题讨论】:

    标签: java spring spring-boot hibernate


    【解决方案1】:

    Hibernate 需要知道在哪里寻找实体类。

    你在做em.setPackagesToScan("com.cbc.coorporateblinddateservice.entities.dates") 但是MeetingsSettingcom.cbc.coorporateblinddateservice.entities.meetinsSetting包中,所以你也需要扫描那个包。

    【讨论】:

    • 嗨,这很有效,谢谢,我必须在 meetingSettings 中将两个配置类都放入 date 中,反之亦然,因为如果我只是将其放入 dateCONfig 中,我会收到以下错误:Use of OneToMany or ManyToMany针对未映射的类。将所有内容放在每个配置中进行扫描可以吗?
    • 你不应该有两种配置,通常每个应用程序有一个(并且绝对不是每个实体类一个)
    • 即使我有一个架构和多个数据库?
    • 如果您有多个数据库,每个数据库都有一个绝对有意义,但根据您发布的代码,它看起来像 MeetingsSetting 和 Date 存在于同一个数据库中(因为它们相互引用)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 1970-01-01
    • 2019-02-24
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    相关资源
    最近更新 更多