将 spel 与 Hibernate Table 和 flyway 结合使用
Using spel with Hibernate Table and flyway
在 application.yml 文件中为 spring 启动应用程序提供这样的 SPEL 表达式 -
database:
schema: '#{"${ENV_VAR:}".equals("")?"DEMO":"DEMO_${ENV_VAR:}"}'
以下在代码中工作,它打印替换值,如 DEMO_XYZ / DEMO if ${ENV_VAR} = XYZ
@Value("${database.schema}")
private String schema;
但是带有 Table 注释的 Hibernate JPA 实体无法将此处启用 SPEL 的变量作为模式 -
@Entity
@Table(name = "TABLE_A", schema="${database.schema}") // prints whole spel expression here
public class TableA { ...
即使在下面也无法使用默认模式为 SPEL 使用替换值 -
spring:
jpa:
show-sql: true
properties:
hibernate:
default_schema: ${database.schema} // prints whole value here as well
似乎 flyway 无法使用已经在 application.yml
中定义的 SPEL 变量
spring:
flyway:
jdbc-url: ...
schemas: ${database.schema}
hibernate.default_schema
和 flyway.schemas
有什么方法可以在同一个 YML 中接受像 ${database.schema}
这样的 SPEL 表达式?
Spring Boot 在 application.yml
中实际上不支持 SpEL。
如果注入 Environment
和
String property = env.getProperty("database.schema");
您会看到占位符已解析,但 SpEL 未解析。
@Value
必须有一些额外的逻辑来进一步向下游解析 SpEL。
通过如下所示以编程方式创建 Hibernate JPA bean 和 Flyway bean 而不是使用 YML 来修复它,因为只有 @Value 注释能够读取 SPEL
database:
schema: '#{"${ENV_VAR:}".equals("")?"DEMO":"DEMO_${ENV_VAR:}"}'
数据库配置
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"com.xyz"})
@EntityScan(basePackages = {"com.xyz"})
public class DbConfig
{
@Value("${database.schema}")
private String schema;
@Bean
public EntityManager entityManager(SessionFactory sessionFactory)
{
return sessionFactory.createEntityManager();
}
@Bean
public PlatformTransactionManager transactionManager()
{
return new JpaTransactionManager();
}
@Bean
public HikariConfig hikariConfig()
{
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName("net.client.jdbc.Driverx");
hikariConfig.setJdbcUrl(url);
Properties props = new Properties();
props.put("user", user);
props.put("password", password);
props.put("db", db);
props.put("schema", schema); // SCHEMA is from SPEL
hikariConfig.setDataSourceProperties(props);
return hikariConfig;
}
@Bean
public DataSource dataSource(HikariConfig hikariConfig)
{
HikariDataSource dataSource = new HikariDataSource(hikariConfig);
return dataSource;
}
@Bean
public LocalSessionFactoryBean entityManagerFactory(DataSource snowflakeDataSource)
{
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(dataSource);
localSessionFactoryBean.setPackagesToScan("com.xyz");
Properties properties = new Properties();
properties.setProperty("hibernate.default_schema", schema);
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.format_sql", "true");
localSessionFactoryBean.setHibernateProperties(properties);
return localSessionFactoryBean;
}
飞路配置
@Value("${database.schema}")
private String schema;
@Bean
public Flyway flyway(DataSource dataSource)
{
Flyway flyWay = Flyway.configure()
.dataSource(dataSource)
.locations("classpath:/somefolder/migrations")
.schemas(schema) // SCHEMA is from SPEL
.baselineVersion("1.0")
.sqlMigrationPrefix("V")
.sqlMigrationSuffixes(".sql")
.placeholders(Map.of("key1", value1,
"key2", value2))
.placeholderReplacement(true)
.placeholderPrefix("%")
.placeholderSuffix("%")
.load();
flyWay.migrate();
return flyWay;
}
在 application.yml 文件中为 spring 启动应用程序提供这样的 SPEL 表达式 -
database:
schema: '#{"${ENV_VAR:}".equals("")?"DEMO":"DEMO_${ENV_VAR:}"}'
以下在代码中工作,它打印替换值,如 DEMO_XYZ / DEMO if ${ENV_VAR} = XYZ
@Value("${database.schema}")
private String schema;
但是带有 Table 注释的 Hibernate JPA 实体无法将此处启用 SPEL 的变量作为模式 -
@Entity
@Table(name = "TABLE_A", schema="${database.schema}") // prints whole spel expression here
public class TableA { ...
即使在下面也无法使用默认模式为 SPEL 使用替换值 -
spring:
jpa:
show-sql: true
properties:
hibernate:
default_schema: ${database.schema} // prints whole value here as well
似乎 flyway 无法使用已经在 application.yml
中定义的 SPEL 变量spring:
flyway:
jdbc-url: ...
schemas: ${database.schema}
hibernate.default_schema
和 flyway.schemas
有什么方法可以在同一个 YML 中接受像 ${database.schema}
这样的 SPEL 表达式?
Spring Boot 在 application.yml
中实际上不支持 SpEL。
如果注入 Environment
和
String property = env.getProperty("database.schema");
您会看到占位符已解析,但 SpEL 未解析。
@Value
必须有一些额外的逻辑来进一步向下游解析 SpEL。
通过如下所示以编程方式创建 Hibernate JPA bean 和 Flyway bean 而不是使用 YML 来修复它,因为只有 @Value 注释能够读取 SPEL
database:
schema: '#{"${ENV_VAR:}".equals("")?"DEMO":"DEMO_${ENV_VAR:}"}'
数据库配置
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"com.xyz"})
@EntityScan(basePackages = {"com.xyz"})
public class DbConfig
{
@Value("${database.schema}")
private String schema;
@Bean
public EntityManager entityManager(SessionFactory sessionFactory)
{
return sessionFactory.createEntityManager();
}
@Bean
public PlatformTransactionManager transactionManager()
{
return new JpaTransactionManager();
}
@Bean
public HikariConfig hikariConfig()
{
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName("net.client.jdbc.Driverx");
hikariConfig.setJdbcUrl(url);
Properties props = new Properties();
props.put("user", user);
props.put("password", password);
props.put("db", db);
props.put("schema", schema); // SCHEMA is from SPEL
hikariConfig.setDataSourceProperties(props);
return hikariConfig;
}
@Bean
public DataSource dataSource(HikariConfig hikariConfig)
{
HikariDataSource dataSource = new HikariDataSource(hikariConfig);
return dataSource;
}
@Bean
public LocalSessionFactoryBean entityManagerFactory(DataSource snowflakeDataSource)
{
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(dataSource);
localSessionFactoryBean.setPackagesToScan("com.xyz");
Properties properties = new Properties();
properties.setProperty("hibernate.default_schema", schema);
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.format_sql", "true");
localSessionFactoryBean.setHibernateProperties(properties);
return localSessionFactoryBean;
}
飞路配置
@Value("${database.schema}")
private String schema;
@Bean
public Flyway flyway(DataSource dataSource)
{
Flyway flyWay = Flyway.configure()
.dataSource(dataSource)
.locations("classpath:/somefolder/migrations")
.schemas(schema) // SCHEMA is from SPEL
.baselineVersion("1.0")
.sqlMigrationPrefix("V")
.sqlMigrationSuffixes(".sql")
.placeholders(Map.of("key1", value1,
"key2", value2))
.placeholderReplacement(true)
.placeholderPrefix("%")
.placeholderSuffix("%")
.load();
flyWay.migrate();
return flyWay;
}