Spring JPA:动态提供架构名称
Spring JPA: Providing Schema Name Dynamically
我正在构建一个 CRUD 应用程序,我在其中使用 spring 数据 jpa 来处理数据库。
我不想在我的实体 class 中提供架构名称,如下所述。
@Entity
@Table(name = "PROPERTY",schema = "ABC")
public class PropertyDTO extends BaseDTO{
//all the properties and getter,setters
}
当我使用 Repository 获取任何结果时,如果我没有在我的实体 class 中提供模式名称,它会抛出一个错误,指出无效的对象名称 属性,是吗我可以提及模式名称的任何其他方式和框架将在触发查询时附加模式名称?
如果您需要在运行时更改模式名称,我建议使用 Hibernate 多租户方法。您可以找到更多详细信息 here and here
您也可以像示例一样使用物理命名策略here
application.properties
spring.jpa.hibernate.naming.physical-strategy=com.example.persistencee.CustomDatabaseIdentifierNamingStrategy
property.schema.name=${PROPERTY_SCHEMA_NAME:abc}
CustomDatabaseIdentifierNamingStrategy
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
}
我正在构建一个 CRUD 应用程序,我在其中使用 spring 数据 jpa 来处理数据库。 我不想在我的实体 class 中提供架构名称,如下所述。
@Entity
@Table(name = "PROPERTY",schema = "ABC")
public class PropertyDTO extends BaseDTO{
//all the properties and getter,setters
}
当我使用 Repository 获取任何结果时,如果我没有在我的实体 class 中提供模式名称,它会抛出一个错误,指出无效的对象名称 属性,是吗我可以提及模式名称的任何其他方式和框架将在触发查询时附加模式名称?
如果您需要在运行时更改模式名称,我建议使用 Hibernate 多租户方法。您可以找到更多详细信息 here and here
您也可以像示例一样使用物理命名策略here
application.properties
spring.jpa.hibernate.naming.physical-strategy=com.example.persistencee.CustomDatabaseIdentifierNamingStrategy
property.schema.name=${PROPERTY_SCHEMA_NAME:abc}
CustomDatabaseIdentifierNamingStrategy
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
}