运行时目录、模式和表映射
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
大多数 SQL 对象类型都带有 org.jooq.Catalog
和 org.jooq.Schema
限定。在多租户应用程序中,用户可能希望将这些标识符命名空间映射到非默认值。
将您的 DEV 模式映射到生产环境
您可能希望以这种方式设计数据库,即拥有多个模式实例。当您希望清晰地分离属于多个客户/组织单位/分支/用户的数据,并将每个实体的数据放入单独的数据库或模式中时,这非常有用。
在我们的 AUTHOR 示例中,这意味着您将为几家公司(如 My Book World 和 Books R Us)提供图书参考数据库。在这种情况下,您可能会有如下的模式设置:
- DEV:您的开发模式。这将是您进行代码生成的模式,jOOQ
- MY_BOOK_WORLD:My Book World 的模式实例
- BOOKS_R_US:Books R Us 的模式实例
使用 jOOQ 将 DEV 映射到 MY_BOOK_WORLD
当 My Book World 的用户登录时,您希望他们使用从 DEV 生成的类来访问 MY_BOOK_WORLD 模式。这可以通过 org.jooq.conf.RenderMapping
类来实现,该类可以配置您的 Configuration 的 设置。请看以下示例:
示例配置
Settings settings = new Settings() .withRenderMapping(new RenderMapping() .withSchemata( new MappedSchema().withInput("DEV") .withOutput("MY_BOOK_WORLD"), new MappedSchema().withInput("LOG") .withOutput("MY_BOOK_WORLD_LOG")));
使用上述映射配置的 Configuration 执行的查询实际上将生成此 SQL 语句:
SELECT * FROM MY_BOOK_WORLD.AUTHOR
DSL.using(connection, dialect, settings) .selectFrom(DEV.AUTHOR)
这是有效的,因为 AUTHOR
是从 DEV
模式生成的,而 DEV
模式已通过上述设置映射到 MY_BOOK_WORLD
模式。
表映射
不仅模式可以映射,表也可以。如果您不是应用程序连接的数据库的所有者,您可能需要为每个表安装一个带有某种前缀的模式。在我们的示例中,这可能意味着您需要将 DEV.AUTHOR 映射到 MY_BOOK_WORLD.MY_APP__AUTHOR,其中 MY_APP__ 是应用于您所有表的缀。这可以通过创建以下映射来实现:
示例配置
Settings settings = new Settings() .withRenderMapping(new RenderMapping() .withSchemata( new MappedSchema().withInput("DEV") .withTables( new MappedTable().withInput("AUTHOR") .withOutput("MY_APP__AUTHOR"))));
使用上述映射配置的 Configuration 执行的查询实际上将生成此 SQL 语句:
SELECT * FROM DEV.MY_APP__AUTHOR
表映射和模式映射可以独立应用,方法是在上述配置中指定多个 MappedSchema 条目。jOOQ 将按出现顺序处理它们,并首次匹配时进行映射。请注意,您可以随时省略 MappedSchema 的输出值,在这种情况下,仅应用表映射。
UDT 映射
不仅模式可以映射,UDT 也可以。如果您不是应用程序连接的数据库的所有者,您可能需要为每个 UDT 安装一个带有某种前缀的模式。在我们的示例中,这可能意味着您需要将 DEV.AUTHOR_TYPE 映射到 MY_BOOK_WORLD.MY_APP__AUTHOR_TYPE,其中 MY_APP__ 是应用于您所有 UDT 的前缀。这可以通过创建以下映射来实现:
示例配置
Settings settings = new Settings() .withRenderMapping(new RenderMapping() .withSchemata( new MappedSchema().withInput("DEV") .withUdts( new MappedUDT().withInput("AUTHOR_TYPE") .withOutput("MY_APP__AUTHOR_TYPE"))));
使用上述映射配置的 Configuration 执行的查询实际上将生成此 SQL 语句:
SELECT CAST(ROW('John', 'Doe') AS DEV.MY_APP__AUTHOR_TYPE)
UDT 映射和模式映射可以独立应用,方法是在上述配置中指定多个 MappedSchema 条目。jOOQ 将按出现顺序处理它们,并首次匹配时进行映射。请注意,您可以随时省略 MappedSchema 的输出值,在这种情况下,仅应用 UDT 映射。
目录映射
对于 SQL Server 等数据库,除了模式之外,还可以映射目录。机制完全相同。因此,我们假设我们为表 [dev].[dbo].[author] 生成了代码,并希望在运行时将其映射到 [my_book_world].[dbo].[author]。可以通过以下方式实现:
示例配置
Settings settings = new Settings() .withRenderMapping(new RenderMapping() .withCatalogs( new MappedCatalog().withInput("DEV") .withOutput("MY_BOOK_WORLD")));
为了让您完全控制每个表的映射方式,MappedCatalog 对象可以包含 MappedSchema(以及 MappedTable)定义。
使用正则表达式
以上所有示例都使用了 1:1 常量名称映射,其中输入和输出模式或表名称由配置固定。使用 jOOQ 3.8,也可以使用正则表达式进行映射,例如:
示例配置
Settings settings = new Settings() .withRenderMapping(new RenderMapping() .withSchemata( new MappedSchema().withInputExpression(Pattern.compile("DEV_(.*)")) .withOutput("PROD_$1") .withTables( new MappedTable().withInputExpression(Pattern.compile("DEV_(.*)")) .withOutput("PROD_$1"))));
与常量版本唯一的区别是,在那种情况下,input
字段被替换为类型为 java.util.regex.Pattern
的 inputExpression
字段,而 output
字段的含义是模式替换,而不是常量替换。
在代码生成时硬编码映射
请注意,本手册关于 代码生成模式映射 的部分解释了如何在代码生成时硬编码您的目录、模式和表映射。
限制
映射的对象需要被 jOOQ org.jooq.RenderContext
了解,这意味着例如 纯 SQL 模板 及其内容无法被映射。有关更多详细信息,请参阅 需要代码生成的特性。
反馈
您对本页面有任何反馈吗? 我们很乐意倾听!