休眠:来自外部jar依赖项的实体

时间:2018-10-18 19:58:00

标签: java mysql database hibernate spring-boot

我有以下问题。我必须使用springboot,hibernate和gradle开发一个应用程序。我的应用程序必须链接到两个不同的数据库,所以我有: application.properties:

spring.db1.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.db1.datasource.url=jdbc:mysql://192.168.1.189:3306/db1?useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&useSSL=false&serverTimezone=UTC
spring.db1.datasource.jdbcUrl=${spring.db1.datasource.url}
spring.db1.datasource.username=test
spring.db1.datasource.password=test

spring.db2.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.second.datasource.url=jdbc:mysql://192.168.1.189:3306/test_db?useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&serverTimezone=UTC
spring.db2.datasource.jdbcUrl=${spring.db2.datasource.url}
spring.db2.datasource.username=test
spring.db2.datasource.password=test

然后,我编写了两个配置类以定义与数据库的连接:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "testDbEntityManager", 
        transactionManagerRef = "testDbTransactionManager")
public class TestdbDbConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.db1.datasource")
    public DataSource testDbDataSource() {
        return DataSourceBuilder
                    .create()
                    .build();
    }

    @Bean(name = "testDbEntityManager")
    public LocalContainerEntityManagerFactoryBean testDbEntityManagerFactory(EntityManagerFactoryBuilder builder) {

        Map<String, Object> properties = hibernateProperties();

        return builder
                    .dataSource(testDbDataSource())
                    .properties(properties)
                    .packages(CustomObject.class)
                    .persistenceUnit("testDb1PU")
                    .build();
    }

    @Bean(name = "testDbTransactionManager")
    public PlatformTransactionManager testDbTransactionManager(@Qualifier("testDbEntityManager") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    private Map<String, Object> hibernateProperties() {

        Resource resource = new ClassPathResource("hibernate.properties");

        try {
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
            return properties.entrySet().stream()
                                            .collect(Collectors.toMap(
                                                        e -> e.getKey().toString(),
                                                        e -> e.getValue())
                                                    );
        } catch (IOException e) {
            return new HashMap<String, Object>();
        }
    }
}

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "testDb2EntityManager", 
        transactionManagerRef = "testDb2TransactionManager")
public class TestdbDbConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.db2.datasource")
    public DataSource testDbDataSource() {
        return DataSourceBuilder
                    .create()
                    .build();
    }

    @Bean(name = "testDb2EntityManager")
    public LocalContainerEntityManagerFactoryBean testDbEntityManagerFactory(EntityManagerFactoryBuilder builder) {

        Map<String, Object> properties = hibernateProperties();

        return builder
                    .dataSource(testDbDataSource())
                    .properties(properties)
                    .packages(AgentCustomGui.class,
                        Area.class,
                        Company.class)
                    .persistenceUnit("testDb2PU")
                    .build();
    }

    @Bean(name = "testDb2TransactionManager")
    public PlatformTransactionManager testDbTransactionManager(@Qualifier("testDb2EntityManager") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    private Map<String, Object> hibernateProperties() {

        Resource resource = new ClassPathResource("hibernate.properties");

        try {
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
            return properties.entrySet().stream()
                                            .collect(Collectors.toMap(
                                                        e -> e.getKey().toString(),
                                                        e -> e.getValue())
                                                    );
        } catch (IOException e) {
            return new HashMap<String, Object>();
        }
    }
}

问题是:对于第二个数据库,实体(AgentCustomGui,Area,Company)是在项目中作为依赖项包含的外部jar中定义的。 当我尝试使用gradle(gradle bootRun)运行应用程序时,出现以下异常:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testDb2EntityManager' defined in class path resource [it/testwebapp/config/TestdbDb2Config.class]: Invocation of init method failed; nested exception is java.lang.NullPointerException
...
Caused by: java.lang.NullPointerException: null
        at org.hibernate.mapping.PersistentClass.createPrimaryKey(PersistentClass.java:363) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
        at org.hibernate.cfg.CreateKeySecondPass.doSecondPass(CreateKeySecondPass.java:31) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
        at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1640) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
        at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1604) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
        at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
        at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:861) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
        at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:888) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
        at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
        at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
        at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1758) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1695) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]

如果我在Web应用程序内部移动实体(例如第一个CustomObject),那么以下休眠属性将使一切工作正常:

hibernate.id.new_generator_mappings=false
hibernate.format_sql=true
hibernate.temp.use_jdbc_metadata_defaults=false
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.current_session_context_class=org.hibernate.context.internal.ThreadLocalSessionContext

我尝试了hibernate.hbm2ddl.auto=validate,但在这种情况下,我还有另一个例外: 无法建立Hibernate SessionFactory;嵌套异常为org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [custom_object]

我还尝试为两种配置都显式地显示default_schema: properties.put("hibernate.default_schema", "db1");properties.put("hibernate.default_schema", "test_db");,但我又有第二个例外。确实,我需要使用外部实体并映射一个双数据源。 谁能帮我?感谢您的支持。

0 个答案:

没有答案