JPA:如何将一些实体映射到另一个数据库实例的不同模式?

Posted

技术标签:

【中文标题】JPA:如何将一些实体映射到另一个数据库实例的不同模式?【英文标题】:JPA: how to map some entities to a different schema of another database instance? 【发布时间】:2020-11-27 18:18:18 【问题描述】:

JPA:有没有办法将一些实体映射到另一个数据库实例的模式?例如,

@Entity
public class Foo 



@Entity
@Table(schema="schema1")
public class Bar 


Bar 实体映射到同一个数据库实例的 schema1。 JPA 中有没有办法将其映射到远程数据库实例中的模式?它对于在多个应用程序之间共享实体很有用。

“目录”可以用于此目的吗?

【问题讨论】:

【参考方案1】:

“远程数据库”是什么意思?

如果您使用 @Table(schema = "myschema", name = "bar"),Hibernate 将使用模式名称限定所有查询(例如,SELECT e FROM Bar 最终将转换为 SELECT * FROM myschema.bar)。如果您用来连接数据库的数据库用户有权访问myschema.bar(无论这样的数据库对象是什么),那么查询将起作用;如果不是,则查询将失败。

如果您的意思是“作为单独服务器的远程数据库”,那么当然,每个持久性上下文只能使用一个 JDBC 连接来连接数据库。如果这是您的情况,也许您应该查阅 RDBMS 的文档以了解连接两个数据库实例的方法(例如,在 Oracle 中,您可以使用数据库链接和同义词)。

不过,请确保您了解其中的含义,因为这样的解决方案会引入其自身的问题类别(包括您的系统中突然出现隐式分布式事务这一事实)。

作为旁注,我不确定这种方法如何“用于在多个应用程序之间共享实体”,或者为什么人们甚至会认为“在多个应用程序之间共享实体”在某种程度上有用,但我会认真考虑通过通过共享/链接数据库集成多个应用程序的想法。它通常会带来比它解决的问题更多的问题。

【讨论】:

例如,所有应用程序都有用户实体。用户可以创建单个帐户来访问所有应用程序。所以用户实体被所有应用程序共享,它们可以存储在数据库服务器的一个模式中。 我了解应用程序需要共享数据。这并不意味着他们应该共享数据库实体。共享数据库的问题是应用程序数据模式不能独立发展。此外,由于持久性上下文中的缓存实体永远不会失效,一个应用程序更新数据会导致其他应用程序出现不一致。您可以拥有一个拥有用户资源的专用应用程序,并通过定义明确的 API(例如 REST)公开其上的所有操作,这仍然使所有其他应用程序都可以访问数据,但不会引入紧密耦合的共享数据库 当使用 Web 服务(或 LDAP)进行用户身份验证时,用户实体与 JPA O/R 映射中的其他实体之间仍然存在关联。用户实体需要映射到 JPA 数据库中的表。所以这将为不同的应用程序创建重复的用户表。有没有办法避免这种情况?谢谢。 嗯,用户域对象和其他域对象之间可以存在关联,但它们不必表示为与实际User 实体的物理关联。您可以只拥有该域对象的表示(通常是userId 属性),并且有关关联的信息仍然存在。而且,如果您需要其他用户信息,您只需在需要时使用 id 从真相源用户服务中检索它。无需将用户数据保存在本地(尽管复制本身也不是坏事,它只是缓存的另一个名称) 明白。但是如果每次从数据库中获取实体列表时使用 web 服务获取用户信息,性能会变慢。例如,使用他们的用户名对 Orders 进行分页。实际应用中性能有多差?谢谢。【参考方案2】:

如果我理解你的意思,你应该使用两个(或更多)不同的持久化上下文

【讨论】:

以上是关于JPA:如何将一些实体映射到另一个数据库实例的不同模式?的主要内容,如果未能解决你的问题,请参考以下文章

JPA:将 OneToOne Long 值(不是实体)映射到另一个不是主键的表列

JPA一对多映射

JPA ManyToMany 映射问题(无法将同一实体映射到另一个)

JPA多对多映射

如何使用 JPA/Hibernate 注释将 MySQL char(n) 列映射到实例变量?

如果相同的表但不同的模式,如何避免重复 jpa 映射(实体、服务、存储库..)?