java - 从数据库中检索一个值并将其设置为Spring boot中的@Table Name值

标签 java spring spring-boot spring-data-jpa lombok

我有一个带有@Table注释的类,目前我直接设置Name值,如下所示:

@Data
@Entity
@NoArgsConstructor
@Table(name = "US_STUDENTS" )
public class Student {

// some properties

}

我在数据库中有一个名为 MasterCountries 的表,其中有一个列名称 - = 国家前缀 - “US_”

当 Spring boot 应用程序运行时,我想从数据库中获取这些数据并将其用作 @Table 名称值的一部分,使其如下所示:

@Data
@Entity
@NoArgsConstructor
@Table(name = countryPrefix + "STUDENTS" ) // so the end result will be "US_STUDENTS"
public class Student {

// some properties

}

我已经谷歌了,但仍然没有找到解决方案,原因是因为我想让它动态化,每当这个 Spring Boot 服务需要重新部署到其他国家时,只需要检索特定的国家前缀来自数据库,因此无需为每个国家/地区部署再次更改代码。

对于存储库,我设置了一个扩展 JpaRepository 的接口(interface),如下所示:

public interface MasterCountriesRepository extends JpaRepository<CountriesSetting, Long> {

    CountriesSetting findByCountryCode(String countryCode);

}

对于CountriesSetting实体:

@Data
@Entity
@NoArgsConstructor
@Table(name = "MasterCountries" )
public class CountriesSetting {

// some properties

}

这可以在 Spring JPA 中实现吗? 请忽略任何错误或轻微的语法问题,因为这不是真正的代码。提前致谢。

最佳答案

注释要求其使用中涉及的所有内容都是编译时常量。这是 Java 规范规定的,你不能要求编译器暂时忘记这个限制。

任何表达式都是“编译时间常量”,如果它是:

  • 文字...但 null 不算数!
  • 格式为 X ! Y,其中 X 和 Y 是“编译时间常数”,! 是一些运算符,例如 + 或 -。
  • 对 [A] 静态、[B] 最终、[C] 类型为 String 或基元的字段的引用,[D] 其初始化表达式为“编译时常量”(递归地使用相同的定义)。

因此,Foo.x 是给定的编译时常量:

class Foo {
   static final int x = 5 - 3 + Integer.MAX_VALUE - Bar.y;
}
class Bar {
   static final int y = 10;
}

但这些不是:

  • static final long z = System.currentTimeMillis();
  • 静态最终字符串 y = null;
  • static Final String a = LocalDate.of(2020, 1, 1).toString();

请注意,第三个似乎是恒定的(该表达式的输出是一成不变的,并且在所有虚拟机上永远相同),但并不重要,因为它在 java lang 规范中没有明确命名.

鉴于您想要从数据库中检索此信息,您想要的是不可能 - 因为您的意图肯定是表名在编译期间被锁定,然而,您提供给注释参数的表达式必须是编译时常量的原因是编译器必须将其锁定。

那么解决方案是什么?

不要使用注释。在运行时查询的注释通常是配置快捷方式。一般来说,有一种更迂回的方式来实现相同的目标,即调用默认为“我将只读出注释值”的 API。

注释也可以在编译时查询 - lombok 就是这样做的,注释处理器也是如此(例如,在编译运行期间生成基于 XML 的配置文件的处理器)。简单地说,您应该很明显您的整个计划不可能起作用 - 这些基本上是“编译时”概念。

更简单的建议

跳出框框思考,也许:

有一个单独的脚本,该脚本将运行一个CREATE OR REPLACE VIEW语句,该语句创建一个具有单一名称的 View (例如,Students),该 View 仅反射(reflect)所声明的表(例如 US_Students),使用 ON INSERTON UPDATE 以及 ON DELETE 也可以“通过”在此 View 上进行的任何插入/更新/删除尝试最终都会影响 US_Students 表。

要“更改”“国家/地区”,只需一次性运行该脚本并重新启动 Java 应用程序,瞧。

如何创建 View 并让它们与删除/插入/更新一起使用取决于您的数据库引擎。在 MySQL 和 postgres 中,简单的 SELECT 的基本 View 没有聚合和连接等“正常工作”。

你实际上只是在看:

CREATE OR REPLACE VIEW Students AS SELECT * FROM US_Students;

运行该语句就可以了。

关于java - 从数据库中检索一个值并将其设置为Spring boot中的@Table Name值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68575584/

相关文章:

java - 在单元测试中等待 Platform.RunLater

java - new <childclass>() 和 new <parentclass>() 有什么区别?

java - 我的 STS 无法运行

java - 处理 Spring Webflux MultipartFile.transferTo 中的错误

java - 从 spring-boot 环境获取属性映射

java - Maven安装j2ee文件夹结构问题(spring,struts..)

java - Spring MVC - 将相同的对象从一个页面传输到另一个页面

java - 通过 jdbc 模板使用两个数据源

docker-compose - 外部化 spring application.properties

android - 如何提取无效的 .apk 文件的代码?