如何在Spring Boot中使用环境变量动态设置tableName?

时间:2018-07-10 10:10:03

标签: java spring spring-boot amazon-dynamodb

我正在使用AWS ECS托管我的应用程序,并使用DynamoDB进行所有数据库操作。因此,对于不同的环境,我将拥有具有不同表名的相同数据库。例如“ dev_users”(用于Dev env),“ test_users”(用于Test env)等。(这就是我们公司在不同环境中使用同一Dynamo帐户的方式)

因此,我想使用通过“ AWS ECS任务定义”环境参数传递的环境变量来更改模型类的“ tableName”。

例如。

我的模型课程是:

@DynamoDBTable(tableName = "dev_users")
public class User {

现在,当我在测试环境中部署容器时,需要用“ test”替换“ dev”。我知道我可以使用

@Value("${DOCKER_ENV:dev}")

访问环境变量。但是我不确定如何在类外使用变量。有什么方法可以使用docker env变量选择表前缀吗?

我的意图是这样使用:

enter image description here

我知道不可能这样。但是还有其他方法或解决方法吗?

编辑1:

我正在研究拉胡尔的答案,并面临一些问题。在写问题之前,我将解释我遵循的过程。

过程:

  1. 我已经在我的配置类(com.myapp.users.config)中创建了这些bean。
  2. 由于我没有存储库,因此将我的Model类包名称指定为“ basePackage”路径。 (请检查图像)

enter image description here

  • 对于1),我已替换了“表名上层bean注入”,以避免出现错误。
  • 对于2),我打印了传递给此方法的名称。但这是空的。因此,请检查在此处传递值的所有可能方法。

检查图像是否有错误:

enter image description here

我没有更改用户模型类中的任何内容,因为在执行bean时bean将替换DynamoDBTable的名称。但是表名超过骑马正在发生。数据仅从“模型类”级别给出的表名称中提取。

我在这里想念什么?

4 个答案:

答案 0 :(得分:2)

可以通过更改的DynamoDBMapperConfig bean更改表名称。

对于必须为每个表加上文字前缀的情况,可以这样添加Bean。这里的前缀可以是您所用环境的名称。

 @Bean
public TableNameOverride tableNameOverrider() {
    String prefix = ... // Use @Value to inject values via Spring or use any logic to define the table prefix
    return TableNameOverride.withTableNamePrefix(prefix);
}

有关更多详细信息,请在此处查看完整的详细信息: https://github.com/derjust/spring-data-dynamodb/wiki/Alter-table-name-during-runtime

答案 1 :(得分:1)

我对其他答案投了赞成票,但这是一个主意:

使用所有用户详细信息创建基类:

@MappedSuperclass
public abstract class AbstractUser {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;

创建2个具有不同表名和spirng配置文件的命令:

@Profile(value= {"dev","default"})
@Entity(name = "dev_user")
public class DevUser extends AbstractUser {
}

@Profile(value= {"prod"})
@Entity(name = "prod_user")
public class ProdUser extends AbstractUser {
}

创建一个使用映射的超类的单个JPA存储库

public interface UserRepository extends CrudRepository<AbstractUser, Long> {
}

然后切换弹簧轮廓的弹性

@RunWith(SpringJUnit4ClassRunner.class)
@DataJpaTest
@Transactional
public class UserRepositoryTest {

    @Autowired
    protected DataSource dataSource;

    @BeforeClass
    public static void setUp() {
        System.setProperty("spring.profiles.active", "prod");
    }

    @Test
    public void test1() throws Exception {

        DatabaseMetaData metaData = dataSource.getConnection().getMetaData();
        ResultSet tables = metaData.getTables(null, null, "PROD_USER", new String[] { "TABLE" });
        tables.next();
        assertEquals("PROD_USER", tables.getString("TABLE_NAME"));
    }
}

答案 2 :(得分:1)

关于在运行时更改表名的需求,我们有同样的问题。我们正在使用Spring-data-dynamodb 5.0.2,以下配置似乎提供了我们所需的解决方案。

首先,我注释了我的bean访问器

@EnableDynamoDBRepositories(dynamoDBMapperConfigRef = "getDynamoDBMapperConfig", basePackages = "my.company.base.package")

我还设置了一个名为ENV_PREFIX的环境变量,该变量是通过SpEL通过Spring连接的。

@Value("#{systemProperties['ENV_PREFIX']}")
private String envPrefix;

然后我设置一个TableNameOverride bean:

@Bean
public DynamoDBMapperConfig.TableNameOverride getTableNameOverride() {
    return DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix(envPrefix);
}

最后,我使用TableNameOverride注入设置了DynamoDBMapperConfig bean。在5.0.2中,我们必须在DynamoDBMapperConfig构建器中设置标准的DynamoDBTypeConverterFactory以避免NPE。

@Bean
public DynamoDBMapperConfig getDynamoDBMapperConfig(DynamoDBMapperConfig.TableNameOverride tableNameOverride) {
    DynamoDBMapperConfig.Builder builder = new DynamoDBMapperConfig.Builder();
    builder.setTableNameOverride(tableNameOverride);
    builder.setTypeConverterFactory(DynamoDBTypeConverterFactory.standard());
    return builder.build();
}

事后看来,我可以设置一个DynamoDBTypeConverterFactory bean,该bean返回一个标准DynamoDBTypeConverterFactory,并使用DynamoDBMapperConfig构建器将其注入到getDynamoDBMapperConfig()方法中。但这也可以做。

答案 3 :(得分:0)

我能够获得以活动配置文件名称为前缀的表名称。

首先添加了TableNameResolver类,如下所示,

        private void ControlRotateModel()
        {

            try
                {
                    ((model)elementHost.Child).rotate3D();
                }
            catch (Exception ex)
                {
                     //
                }

        }

然后按如下所示设置DynamoDBMapper bean,

@Component
public class TableNameResolver extends DynamoDBMapperConfig.DefaultTableNameResolver {

private String envProfile;

public TableNameResolver() {}

public TableNameResolver(String envProfile) {
    this.envProfile=envProfile;
}

 @Override
 public String getTableName(Class<?> clazz, DynamoDBMapperConfig config) {
  String stageName = envProfile.concat("_");
  String rawTableName = super.getTableName(clazz, config);
  return stageName.concat(rawTableName);
 }
}

添加了变量envProfile,这是一个可从application.properties文件访问的活动配置文件属性值。

@Bean
@Primary
public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB) {

    DynamoDBMapper mapper = new DynamoDBMapper(amazonDynamoDB,new DynamoDBMapperConfig.Builder().withTableNameResolver(new TableNameResolver(envProfile)).build());
     return mapper;
}