Spring JPA:动态提供模式名称

Posted

技术标签:

【中文标题】Spring JPA:动态提供模式名称【英文标题】:Spring JPA: Providing Schema Name Dynamically 【发布时间】: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,有没有其他方法可以提及架构名称和框架将在触发查询时附加架构名称?

【问题讨论】:

看起来 HibernateInterceptor 是一种选择。更多信息***.com/questions/25283767/… 【参考方案1】:

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

【讨论】:

【参考方案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”不存在 也试过这个:***.com/questions/65660340/…面临同样的错误。

以上是关于Spring JPA:动态提供模式名称的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA 动态拼接条件的通用设计模式

Spring-boot JPA 连接到 postgres,其中在运行时提供数据库和模式

Spring提供的JPA的分页的功能,和动态搜索后进行显示的分页功能的设置

具有任意 AND 子句的动态 spring 数据 jpa 存储库查询

spring data jpa封装specification实现简单风格的动态查询

Spring with Hibernate-如何动态传递模式名称