使用JPA在运行时更改表名

时间:2018-03-21 21:17:35

标签: java hibernate jpa

我实现了一个使用数据库的服务。数据库中有几个表。这些表中存储了一些计算结果。另一个服务为每个计算创建一个新表,现在表的列表如下所示:

  • calculation_1_0
  • calculation_2_0
  • calculation_2_1
  • calculation_2_2
  • calculation_3_0
  • calculation_X_Y

所有表的表结构都相同。

是否可以使用JPA从这些表中获取数据而不为每个表创建实体?

2 个答案:

答案 0 :(得分:2)

在运行时创建表是个坏主意。鉴于您知道列是什么,更好的设计是拥有calculation_type查找表并在计算表中创建外键并对其进行索引。然后,您可以预先创建实体并具有更好的关系完整性。

要直接回答问题,无法动态创建新表,然后使用JPA进行映射。你可以使用普通的JDBC,但是JPA不支持它的原因 - 这是糟糕的设计。

答案 1 :(得分:0)

  

@krokodilko我绝对同意你的意见,但我不负责任   改变设计结构,因为我不是它的开发者,我只是   用它来实现我的目标。

如果你必须忍受它,那么我会动态删除/创建一个视图或同义词来欺骗JPA。我的想法是:

  • 在加载EntityManager之前,创建一个具有固定名称的视图/同义词,将所选表格映射到该公用名称
  • JPA中的
  • 使用XML或注释将实体映射到此通用名称的视图/同义词
  • 加载实体管理员

这种方法存在不足之处:

  • 应用程序中只有一个实例/线程可以同时使用此视图/同义词,这在多用户环境中不起作用(除非所有实例/线程都已同步,并且当时将同时关闭/打开实体管理器)当视图被更新/重新创建时 - 但我甚至无法想象这样的解决方案,它将是一个包含许多陷阱和错误的巨大项目)
  • 一次只能使用一个表,为了使用另一个表,必须关闭实体管理器,必须删除视图/同义词,然后再次创建,然后必须再次加载实体管理器

您还可以创建一个联合多个表的视图,如下所示:

CREATE VIEM my_common_name AS
SELECT '1_0' as calc_name, t.* FROM calculation_1_0 t UNION ALL
SELECT '2_0' as calc_name, t.* FROM calculation_2_0 t UNION ALL
.....
.....
SELECT 'X_Y' as calc_name, t.* FROM calculation_X_Y t

但是再次 - 如果进程创建了一个新表,则必须关闭实体管理器,使用新表名重新创建此视图,然后再次加载实体管理器。

从性能角度来看,这将是非常糟糕的 - 你不能在这个视图上创建任何索引,它不能被分区,也不能被调整或实现​​,对这个怪物视图的每个查询几乎总是会对所有这些表进行全表扫描。

首先进行了糟糕的数据库结构设计,就像设计具有不同充电插座的手机一样,每次为手机充电时都需要使用不同的插头。最好的办法是修复这个原始错误,因为这样的修复非常容易,只需创建一个带有附加列“calculation_name”的公共表,并修复一个将数据保存到这些表的代码表(将数据插入公共表而不是每次都创建新表),其他一切都将是解决此问题的麻烦尝试。

如果我是你,那么我会去找我的经理,我会告诉他,这样的技术问题设计不好。我会告诉他我们现在可以解决它,它会花费一点($)。我会告诉他,如果我们现在不修复它,那么这个功能的每一个未来变化都会越来越麻烦和昂贵($$,$$$,$$$$$ - 因为人工日的成本,维护,性能/硬件等),最终这样的修复将是根本不可能的,我们将不得不从头开始重写这个系统(这将花费我们$$$$$$$)。
经理有一个更广阔的视野,他应该知道商业计划,他应该知道这个功能是否会在未来发展,或者可能会在半年后被放弃。这是经理的决定 - 现在投资$并在未来保存$$$$$,或者不做任何事情,因为它将来不会给我们任何利润。