【问题标题】:Spring JPA: Providing Schema Name DynamicallySpring JPA:动态提供模式名称
【发布时间】:2020-08-28 20:00:40
【问题描述】:

我正在构建一个 CRUD 应用程序,我在其中使用 spring data jpa 来处理数据库。 我不想在我的实体类中给出架构名称,如下所述。

 @Entity
 @Table(name = "PROPERTY",schema = "ABC")
 public class PropertyDTO extends BaseDTO{
     //all the properties and getter,setters
 }

当我使用 Repository 获取任何结果时,如果我没有在 My Entity 类中提供架构名称,它会抛出一个错误,说无效的对象名称 PROPERTY,有没有其他方法可以提及架构名称和框架将在触发查询时附加架构名称?

【问题讨论】:

标签: java hibernate spring-boot spring-data-jpa hibernate-entitymanager


【解决方案1】:

如果您需要在运行时更改架构名称,我建议使用 Hibernate 多租户方法。你可以找到更多细节herehere

【讨论】:

    【解决方案2】:

    您也可以使用物理命名策略,如示例here

    application.properties

    spring.jpa.hibernate.naming.physical-strategy=com.example.persistencee.CustomDatabaseIdentifierNamingStrategy
    property.schema.name=${PROPERTY_SCHEMA_NAME:abc}
    

    自定义数据库标识符命名策略

    package com.example.persistence;
    
    import lombok.extern.slf4j.Slf4j;
    import org.hibernate.boot.model.naming.Identifier;
    import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
    import org.springframework.beans.BeansException;
    import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.core.env.Environment;
    import org.springframework.stereotype.Component;
    
    import java.io.Serializable;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    @Component
    @Slf4j
    public class CustomDatabaseIdentifierNamingStrategy extends SpringPhysicalNamingStrategy implements ApplicationContextAware {
    
        private final Pattern VALUE_PATTERN = Pattern.compile("^\\$\\{([\\w.]+)}$");
        private Environment environment;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            environment = applicationContext.getBean(Environment.class);
        }
    
        @Override
        public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment) {
            return apply(name, jdbcEnvironment);
        }
    
        private Identifier apply(Identifier name, JdbcEnvironment jdbcEnvironment) {
            if (name == null) {
                return null;
            }
    
            String logicalText = name.getText();
            String physicalText = getPhysicalText(logicalText);
            if (physicalText != null) {
                log.info("Created database namespace [logicalName={}, physicalName={}]", logicalText, physicalText);
                return getIdentifier(physicalText, name.isQuoted(), jdbcEnvironment);
            }
            return null;
        }
    
        private String getPhysicalText(String logicalText) {
            String physicalText = null;
            Matcher matcher = VALUE_PATTERN.matcher(logicalText);
            if (matcher.matches()) {
                String propertyKey = matcher.group(1);
                physicalText = environment.getProperty(propertyKey);
                if (physicalText == null) {
                    log.error("Environment property not found for key {}", propertyKey);
                }
            } else {
                log.error("Property key {} is not in pattern {}", logicalText, VALUE_PATTERN);
            }
            return physicalText;
        }
    }
    

    PropertyDTO

    @Entity
    @Table(name = "PROPERTY", schema = "${property.schema.name}")
    public class PropertyDTO extends BaseDTO {
        // all the properties and getter, setters
    }
    

    【讨论】:

    • CustomDatabaseIdentifierNamingStrategy - 创建数据库命名空间 [logicalName=${property.schema.name}, physicalName=my_schema]} ,仍然出现错误:关系“config_details”不存在
    • 也试过这个:stackoverflow.com/questions/65660340/…面临同样的错误。
    猜你喜欢
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多