有一个使用 Java + Hibernate + PostgreSQL 的企业应用程序。 Hibernate 是通过 Java 源代码中的注释进行配置的。到目前为止,数据库模式是固定的,但我面临着它需要动态的问题:我可以从不同位置接收数据,并且必须将它们存储在不同的表中。这意味着我必须在运行时创建表。
幸运的是,似乎来自不同机构的所有这些数据都可以具有相同的模式。但我仍然不知道如何使用 Hibernate 来做到这一点。有两个主要问题:
- 如何告诉 Hibernate 许多不同的表具有相同的结构?例如,“Patient”类不仅可以映射到“Patient”表,还可以映射到“Patient_mayo_clinic”表、“Patient_northwestern”表等。我可以感觉到这会导致歧义:当我访问哪个表时,Hibernate 如何知道要访问哪个表对 Patient 类进行操作?它可以是前面列出的任何一个(但只能是一个)表。
- 如何使用 Hibernate 动态创建表并将类绑定到它们?
对建议的回应:
感谢您的所有建议。到目前为止,所有答案都不鼓励动态创建表。我将标记 Axel 的答案,因为它实现了某些目标,并且它是受支持的解决方案。更具体地说,它称为多租户。有时了解一些描述我们的问题(或问题的一部分)的重要短语很重要。
以下是一些有关多租户的链接:
在现实场景中,多租户还涉及数据集相互隔离的领域(也包括不同凭据的访问和授权)被塞进一张桌子里。
There's an enterprise application using Java + Hibernate + PostgreSQL. Hibernate is configured via annotations in the Java source code. So far the database schema is fixed, but I faced the problem that it needs to be dynamic:I can receive data from different locations and I have to store these in different tables. This means that I have to create tables run-time.
Fortunately, it seems that all of these data coming from the different institutes can have the same schema. But I still don't know how to do that using Hibernate. There are two main problems:
- How to tell to Hibernate that many different tables have the same structure? For example the "Patient" class can be mapped to not just the "patient" table, but the "patient_mayo_clinic" table, "patient_northwestern" table, etc. I can feel that this causes ambiguity: how Hibernate knows which table to access when I do operations on the Patient class? It can be any (but only one) of the former listed tables.
- How can I dynamically create tables with Hibernate and bind a class to them?
Response to suggestions:
Thanks for all of the suggestions. So far all of the answers discouraged the dynamic creation of tables. I'll mark Axel's answer, since it achieves certain goals, and it is a supported solution. More specifically it's called multi-tenancy. Sometimes it's important to know some important phrases which describes our problem (or part of our problem).
Here are some links about multi-tenancy:
In real world scenario multi-tenancy also involves the area of isolating the sets of data from each other (also in terms of access and authorization by different credentials) once they are shoved into one table.
发布评论
评论(4)
Hibernate 无法做到这一点。
为什么不使用研究所列来扩展您的患者表呢?
这样您就能够区分,而不会遇到映射问题。
You can't do this with Hibernate.
Why not extend your patient table with an institute column?
This way you'll be able to differentiate, without running into mapping issues.
恐怕你不能在 Hibernate 中轻松地做到这一点。您必须生成 Java 源代码,对其进行编译,将其添加到类路径中并使用 java.reflection 包动态加载它。如果这有效的话,我对此表示怀疑,这将是一个丑陋的解决方案(恕我直言)。
您是否考虑使用无模式数据库,即:NoSQL 数据库 或 RDF
数据库。它们在可以存储的内容方面要灵活得多,基本上,事情并不严格遵守关系模式。
I am afraid you can't do this easily in Hibernate. You would have to generate the Java source, compile it, add it to your classpath and load it dynamically with java.reflection package. If that works, which I doubt it, it will be an ugly solution (IMHO).
Have you consider using a schema less database i.e: NoSQL databases or RDF
databases. They are much more flexible in terms of what you can store in them , basically things are not tight up against a relational schema.
在大多数环境中,动态创建表并不是一个好主意,因为 dbas 不会授予您在生产中创建表的权限。
阿克塞尔的答案可能适合您。另请参阅 Hibernate 的继承映射 。
In most environments it is not a good idea to create tables dynamically simply because dbas will not give you the rights to create tables in production.
Axel's answer may be right for you. Also look into Inheritance Mapping for Hibernate.
我同意动态创建表是不可取的,但它是可行的。
就我个人而言,我会按照 Axel Fontaine 的建议去做,但如果动态表对你来说是必须的,我会考虑使用 分区。
PostgreSQL 允许您创建一个主表和几个子表(分区),子表之间的记录是分离的,但任何子表中的每条记录在父表中都是可见的。这意味着您可以仅使用简单的插入语句将行插入到您想要的任何子表中(它不酷,但与组合和持久化实体具有相同的复杂程度,因此在您的情况下是可以接受的)以及使用HQL查询数据库
I agree that its not advisable to create tables dynamically nevertheless it's doable.
Personally i would do as Axel Fontaine proposed but if dynamic tables is a must-have for you I would consider using Partitioning.
PostgreSQL allows you to create ona main table and few child tables (partitions), records are disjunctive between child tables, but every record from any child table is visible in parent table. This means that you can insert rows into any child table you want using just simple insert statement (its not cool but has the same level of complexity as composing and persisting an entity, so its acceptable in your case) and query database using HQL