简体   繁体   English

spring 引导中的动态表名称 Jpa

[英]Dynamic table name in spring boot with Jpa

My requirement:我的要求:

My requirement is to read the table name from properties file.我的要求是从属性文件中读取表名。

its working fine as expected without custom database configuration.在没有自定义数据库配置的情况下,它可以正常工作。

when i declare the following way, its working fine.当我声明以下方式时,它工作正常。

spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.properties.hibernate.default_schema=upload
#spring.jpa.hibernate.ddl-auto=create-drop
#sample.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect    
spring.jpa.propertie.hibernate.physical_naming_strategy=com.example.demo.entities.TableNameStrategy.

but when i do custom database configuration, i am getting the following error但是当我进行自定义数据库配置时,我收到以下错误

Caused by: java.lang.NullPointerException: null
    at com.example.demo.entities.TableNameStrategy.toPhysicalTableName(TableNameStrategy.java:25) ~[classes/:na]
    at org.hibernate.boot.model.relational.Namespace.createTable(Namespace.java:92) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.addTable(InFlightMetadataCollectorImpl.java:772) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.hibernate.cfg.annotations.TableBinder.buildAndFillTable(TableBinder.java:509) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.hibernate.cfg.annotations.EntityBinder.bindTable(EntityBinder.java:848) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:647) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:250) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:231) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:274) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) ~[spring-orm-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    ... 17 common frames omitted

Here is my custom database configuration code :这是我的自定义数据库配置代码

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef="sampleEntityManager", 
                       transactionManagerRef="sampleTransactionManager",
                       basePackages= {"com.example.demo.repo"})
public class SampleConfiguration {


    @Autowired
    Environment env;



    @Bean(name="sampleDataSource")
    @Primary
    public DataSource dmsDataSource() { 

          DriverManagerDataSource dataSource = new DriverManagerDataSource();

          dataSource.setDriverClassName(env.getProperty("sample.datasource.driver-class-name"));
          dataSource.setUrl(env.getProperty("sample.datasource.url"));
          dataSource.setUsername(env.getProperty("sample.datasource.username"));
          dataSource.setPassword(env.getProperty("sample.datasource.password"));

        return dataSource;
    }


    @Primary
    @Bean(name = "sampleEntityManager")
    public LocalContainerEntityManagerFactoryBean dmsEntityManagerFactory(EntityManagerFactoryBuilder builder) {

        HashMap<String, Object> properties = new HashMap<>();
        properties.put("hibernate.jdbc.lob.non_contextual_creation",env.getProperty("sample.jpa.properties.hibernate.jdbc.lob.non_contextual_creation"));
        properties.put("hibernate.default_schema", env.getProperty("sample.jpa.properties.hibernate.default_schema"));
        properties.put("hibernate.ddl-auto", env.getProperty("sample.jpa.properties.hibernate.ddl-auto"));
        properties.put("hibernate.physical_naming_strategy",env.getProperty("sample.jpa.properties.hibernate.physical_naming_strategy"));

        return builder
                    .dataSource(dmsDataSource())
                    .properties(properties)
                    .packages("com.example.demo.entities")
                    .persistenceUnit("dms")
                    .build();
    }

    @Primary
    @Bean(name = "sampleTransactionManager")
    public PlatformTransactionManager dmsTransactionManager(@Qualifier("sampleEntityManager") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

this is class where i am defining my table name:这是 class 我在其中定义我的表名:

 @Configuration 
   public class TableNameStrategy extends org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy implements Serializable {

    public static final PhysicalNamingStrategyStandardImpl INSTANCE = new PhysicalNamingStrategyStandardImpl();

    @Autowired 
    Environment env;

    @Override public Identifier toPhysicalTableName(Identifier name,JdbcEnvironment context) {
        return new Identifier(name.toIdentifier(env.getProperty("tableName")).getText(),
                        name.isQuoted());
    } 

}

My properties file:我的属性文件:

sample.datasource.url=jdbc:postgresql://localhost:5432/postgres
sample.datasource.username=postgres
sample.datasource.password=postgres
sample.datasource.driver-class-name=org.postgresql.Driver
sample.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
sample.jpa.properties.hibernate.default_schema=upload
sample.jpa.hibernate.ddl-auto=create-drop
sample.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect 
sample.jpa.propertie.hibernate.physical_naming_strategy=com.example.demo.configuration.TableNameStrategy

tableName=dynamictable //table name

My entity Class我的实体 Class

@Entity
@Data
public class Sample {

    @Id
    private Integer id;

}

with custom database configuration, its not working as expected.使用自定义数据库配置,它无法按预期工作。 can anyone tell me where i am making mistakes?谁能告诉我我在哪里犯错?

Specified property in application.properties is not correct. application.properties中的指定属性不正确。

What you specified: spring.jpa.propertie.hibernate.physical_naming_strategy=com.example.demo.entities.TableNameStrategy您指定的内容: spring.jpa.propertie.hibernate.physical_naming_strategy=com.example.demo.entities.TableNameStrategy

Correct: spring.jpa.hibernate.naming.physical-strategy=com.example.demo.entities.TableNameStrategy正确: spring.jpa.hibernate.naming.physical-strategy=com.example.demo.entities.TableNameStrategy

I suggest you to check argument if it is required because it can cause NullPointerException.如果需要,我建议您检查参数,因为它可能导致 NullPointerException。

@Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) {
    return new Identifier(toIdentifier(getTableName()).getText(), name.isQuoted());
}

private String getTableName() {
    return environment.getRequiredProperty(PROPERTY_TABLE_NAME);
}

because Identifier.toIdentifier can return null value.因为 Identifier.toIdentifier 可以返回 null 值。

public static Identifier toIdentifier(String text) {
    if ( StringHelper.isEmpty( text ) ) {
        return null;
    }
...
}
public final class StringHelper {
...
public static boolean isEmpty(String string) {
    return string == null || string.isEmpty();
}
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM